cpp
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
TimePoint expectedVsyncTime) {
pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);
ui::PhysicalDisplayVector<PhysicalDisplayId> presentableDisplays = {pacesetterPtr->displayId};
{
FrameTargets targets;
targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target());
const bool followerDisplayBackpressure =
FlagManager::getInstance().follower_display_backpressure();
if (!followerDisplayBackpressure) {
expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime();
}
..............先省略.....................................
targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr);
targets.try_emplace(id, &targeter.target());
presentableDisplays.push_back(id);
}
// 执行surfaceflinger::commit的方法
if (!compositor.commit(pacesetterPtr->displayId, targets)) {
compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
mSchedulerCallback.onCommitNotComposited();
return;
}
}
// The pacesetter may have changed or been registered anew during commit.
pacesetterPtr = pacesetterPtrLocked();
//执行surfaceflinger::composite的合成的方法
const auto resultsPerDisplay = compositor.composite(pacesetterPtr->displayId, targeters);
compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
compositor.sample();
for (const auto& [id, targeter] : targeters) {
const auto resultOpt = resultsPerDisplay.get(id);
LOG_ALWAYS_FATAL_IF(!resultOpt);
targeter->endFrame(*resultOpt);
}
}
先分析commit的方法。核心的提交的入口,每帧由Scheduler调用。pacesetterId是主显示器(决定VSync节奏),frameTargets包含所有显示器的帧时间目标。
cpp
bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
const scheduler::FrameTargets& frameTargets) EXCLUDES(mStateLock) {
const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get();
//提取pacesetter显示器的帧目标及其Vsync_Id
const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
if (pacesetterFrameTarget.didMissFrame()) {
mTimeStats->incrementMissedFrames();
}
// SF::processHotplugDisconnect() does not immediately propagate the display removal to the
// Scheduler and CompositionEngine, but instead requires a call to processDisplayChangesLocked()
// to process the rest in the next commit. We should retry the commit with the new pacesetter
// after display transactions have been propagated.
{
//支持动态pacesetter切换。如果开启了pacesetter_selection flag且当前pacesetter已被移除(热插拔),先处理显示器变更,重新调度下一帧本次commit直接返回false,不合成
const bool hasPacesetterDisplay =
FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays.contains(pacesetterId));
if (FlagManager::getInstance().pacesetter_selection() && !hasPacesetterDisplay) {
FTL_FAKE_GUARD(mStateLock, processDisplayChangesLocked());
mScheduler->scheduleFrame();
return false;
}
}
// If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
//如果有显示器正在进行模式切换且fence还未触发,推迟本帧,等待模式切换完成。避免模式切换过程中提交新帧导致的crash
if (std::any_of(frameTargets.begin(), frameTargets.end(),
[this](const auto& pair) FTL_FAKE_GUARD(kMainThreadContext) {
const auto [displayId, target] = pair;
return target->isFramePending() &&
mDisplayModeController.isModeSetPending(displayId);
})) {
mScheduler->scheduleFrame();
return false;
}
{
Mutex::Autolock lock(mStateLock);
for (const auto [displayId, _] : frameTargets) {
//遍历所有目标显示器,完成已就绪的模式切换。若某显示器还没就绪,重新调度并返回false
if (mDisplayModeController.isModeSetPending(displayId)) {
if (!finalizeDisplayModeChange(displayId)) {
mScheduler->scheduleFrame();
return false;
}
}
}
}
//检测HWWC是否背压。若开启GPU合成回退或已miss HWC帧,则
//1、通知VSyncTracker本帧miss
//2、计算已消耗的时间
//3、重新调度commit,本帧放弃合成
if (pacesetterFrameTarget.wouldBackpressureHwc()) {
if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
mScheduler->getVsyncSchedule()->getTracker().onFrameMissed(
pacesetterFrameTarget.expectedPresentTime());
const Duration slack = TimePoint::now() - pacesetterFrameTarget.frameBeginTime();
scheduleCommit(FrameHint::kNone, slack);
return false;
}
}
SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Commit");
const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
// Save this once per commit + composite to ensure consistency
// TODO: b/240619471 - Consider removing front internal display check once AOD is fixed
const auto frontInternalDisplay = FTL_FAKE_GUARD(mStateLock, getFrontInternalDisplayLocked());
mPowerHintSessionEnabled = mPowerAdvisor->usePowerHintSession() && frontInternalDisplay &&
frontInternalDisplay->getPowerMode() == hal::PowerMode::ON;
//判断是否启用启用了动态性能框架
if (mPowerHintSessionEnabled) {
mPowerAdvisor->setCommitStart(pacesetterFrameTarget.frameBeginTime());
mPowerAdvisor->setExpectedPresentTime(pacesetterFrameTarget.expectedPresentTime());
// Frame delay is how long we should have minus how long we actually have.
const Duration idealSfWorkDuration =
mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration;
const Duration frameDelay =
idealSfWorkDuration - pacesetterFrameTarget.expectedFrameDuration();
//计算frame delay (理想状态SF工作时长-实际可用时长),上报给PowerAdvisor用于CPU/GPU频率调节
mPowerAdvisor->setFrameDelay(frameDelay);
mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);
const Period idealVsyncPeriod =
mDisplayModeController.getActiveMode(pacesetterId).fps.getPeriod();
//更新工作的时长
mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod);
}
//刷新率切换指示器、HDR/SDR比例指示器的逐帧动画更新
if (mRefreshRateOverlaySpinner) {
Mutex::Autolock lock(mStateLock);
for (const auto& [_, display] : mDisplays) {
display->animateRefreshRateOverlay();
}
}
if (mHdrSdrRatioOverlay) {
Mutex::Autolock lock(mStateLock);
for (const auto& [_, display] : mDisplays) {
display->animateHdrSdrRatioOverlay();
}
}
// Composite if transactions were committed, or if requested by HWC.
//读取并清零mustComposite标志
bool mustComposite = mMustComposite.exchange(false);
{//FrameTimeline 记录SF唤醒时间,Vsync周期,刷新率(用于jank追踪)
mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId),
pacesetterFrameTarget.frameBeginTime().ns(),
Fps::fromPeriodNsecs(vsyncPeriod.ns()),
mScheduler->getPacesetterRefreshRate());
//清除并获取事务刷新的标志
const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
bool transactionsAreEmpty = false;
//处理所有待提交的事务
//1、更新每个Layer的drawing state,返回是否有变更需要合成
mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
pacesetterFrameTarget.expectedPresentTime().ns(),
flushTransactions, transactionsAreEmpty);
// Tell VsyncTracker that we are going to present this frame before scheduling
// setTransactionFlags which will schedule another SF frame. This was if the tracker
// needs to adjust the vsync timeline, it will be done before the next frame.
//需要合成,通知VSyncTracker帧开始(用于动态调整VSync相位)
if (mustComposite) {
mScheduler->getVsyncSchedule()
->getTracker()
.onFrameBegin(pacesetterFrameTarget.expectedPresentTime(),
pacesetterFrameTarget.lastSignaledFrameTime());
}
if (transactionFlushNeeded()) {
setTransactionFlags(eTransactionFlushNeeded);
}
// This has to be called after latchBuffers because we want to include the layers that have
// been latched in the commit callback
if (transactionsAreEmpty) {
// Invoke empty transaction callbacks early.
//空事务--->发送所有回调
mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */);
} else {
// Invoke OnCommit callbacks.
//非空事务--->仅发送OnCommit回调
mTransactionCallbackInvoker.sendCallbacks(true /* onCommitOnly */);
}
}
// Layers need to get updated (in the previous line) before we can use them for
// choosing the refresh rate.
// Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
// and may eventually call to ~Layer() if it holds the last reference
//刷新率选择与显示器模式变更发起
{
SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Refresh Rate Selection");
//保存并清零updateAttachedChoreographer标志
bool updateAttachedChoreographer = mUpdateAttachedChoreographer;
mUpdateAttachedChoreographer = false;
Mutex::Autolock lock(mStateLock);
//根据需要的内容选择刷新率
mScheduler->chooseRefreshRateForContent(&mLayerHierarchyBuilder.getHierarchy(),
updateAttachedChoreographer);
initiateDisplayModeChanges();
}
//光标位置异步更新(低延迟,不阻塞主线程)
updateCursorAsync();
//仅当不合成时更新InputFlinger(窗口输入区域)。合成时会在onCompositionPresented中更新,避免重复
if (!mustComposite) {
updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime());
}
doActiveLayersTracingIfNeeded(false, mVisibleRegionsDirty,
pacesetterFrameTarget.frameBeginTime(), vsyncId);
mLastCommittedVsyncId = vsyncId;
persistDisplayBrightness(mustComposite);
// 返回值:本帧是否需要合成 mustComposite 启动阶段不合成
return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}
接下来看下合成时期的代码:composite()方法
csharp
CompositeResultsPerDisplay SurfaceFlinger::composite(
PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
SFTRACE_ASYNC_FOR_TRACK_BEGIN(WorkloadTracer::TRACK_NAME, "Composition",
WorkloadTracer::COMPOSITION_TRACE_COOKIE);
//获取主显示器的帧目标
const scheduler::FrameTarget& pacesetterTarget =
frameTargeters.get(pacesetterId)->get()->target();
//提取vsyncId,设置trace名称便于perfetto关联帧
const VsyncId vsyncId = pacesetterTarget.vsyncId();
SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
//创建传给 CompositionEngine 的刷新参数对象。
compositionengine::CompositionRefreshArgs refreshArgs;
//把 SF 自身设为 ADPF power callback(负载升高时可 hint)。
// adpf load up hint
refreshArgs.powerCallback = this;
//在 mStateLock 假守卫下读显示器列表,预留 outputs 容量。
const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
//收集所有 display id,trace 各屏电源模式,并告知 PowerAdvisor 当前有哪些屏。
refreshArgs.outputs.reserve(displays.size());
std::vector<DisplayId> displayIds;
for (const auto& [_, display] : displays) {
displayIds.push_back(display->getId());
display->tracePowerMode();
}
mPowerAdvisor->setDisplays(displayIds);
//把本帧需要从缓存剔除的 buffer id 挪进 refreshArgs(避免重复 uncache)。
refreshArgs.bufferIdsToUncache = std::move(mBufferIdsToUncache);
refreshArgs.outputColorSetting = mDisplayColorSetting;
refreshArgs.forceOutputColorMode = mForceColorMode; //输出颜色策略与强制 color mode。
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty; //可见区域脏 → 本帧要重算 output 几何。
refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) ||
mVisibleRegionsDirty || mDrawingState.colorMatrixChanged;
refreshArgs.internalDisplayRotationFlags = getFrontInternalDisplayRotationFlags(); //内屏旋转标志(影响 buffer transform)
//若颜色矩阵变了,写入矩阵并清标志(少见路径,CC_UNLIKELY)。
if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
mDrawingState.colorMatrixChanged = false;
}
//按调试开关 / 慢 follower 屏等,把某些 layer stack 强制标为 GPU(client)合成。
setForcedClientCompositionLayerStacks(refreshArgs);
// TODO(b/255601557) Update frameInterval per display
//用 pacesetter 的 expected present time 算下一帧 interval(目前全局一份,TODO 按屏)。
refreshArgs.frameInterval =
mScheduler->getNextFrameInterval(pacesetterId, pacesetterTarget.expectedPresentTime());
//若 Scheduler 已 schedule 下一帧,带上 callback 时间。
const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult();
const auto scheduledFrameTimeOpt = scheduledFrameResultOpt
? std::optional{scheduledFrameResultOpt->callbackTime}
: std::nullopt;
refreshArgs.scheduledFrameTime = scheduledFrameTimeOpt;
refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
const auto presentTime = systemTime();
refreshArgs.refreshStartTime = presentTime; //记录"即将进 CompositionEngine"的系统时间,既作 refreshStartTime,也给后面的 onCompositionPresented 用。
//把 displays 拆成:主线程要 present 的 outputs,以及可选的可卸载到后台 GPU 合成的 outputs(多屏优化)。
//C++语法,结构化绑定的变量,addOutputsToRefreshArgs返回一个结构化的变量
auto [mainThreadRefreshArgs, optionalOffloadedRefreshArgs] =
addOutputsToRefreshArgs(pacesetterId, refreshArgs, frameTargeters);
//kCursorOnly=false:处理全部层,不只是光标。把主线程 outputs 对应的 layer snapshot 填进 args,返回 (Layer*, LayerFE*) 列表。
constexpr bool kCursorOnly = false;
const auto layers = addLayerSnapshotsToCompositionArgs(mainThreadRefreshArgs, kCursorOnly);
//预合成准备:必要时置 visible region dirty;对每层 onPreComposition;挂上 release fence future。
prepareLayersForComposition(mainThreadRefreshArgs, kCursorOnly, layers);
//校验 / 配置 readback(截图一类需求)。
for (auto& [layer, layerFE] : layers) {
validateForReadback(layerFE);
}
setupOutputsForReadback(mainThreadRefreshArgs.outputs);
std::vector<std::pair<Layer*, LayerFE*>> offloadedLayers;
if (optionalOffloadedRefreshArgs) {
offloadedLayers =
addLayerSnapshotsToCompositionArgs(*optionalOffloadedRefreshArgs, kCursorOnly);
prepareLayersForComposition(*optionalOffloadedRefreshArgs, kCursorOnly, offloadedLayers);
}
std::unordered_set<uint32_t> mainThreadLayerStacks;
for (auto& output : mainThreadRefreshArgs.outputs) { //收集主线程 outputs 的 layerStack,后面用来分流 "有排队帧的层"。
mainThreadLayerStacks.insert(output->getState().layerFilter.layerStack.id);
}
//预留 layersWithQueuedFrames 容量。
mainThreadRefreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
if (optionalOffloadedRefreshArgs) {
optionalOffloadedRefreshArgs->layersWithQueuedFrames.reserve(
mLayersWithQueuedFrames.size());
}
//遍历 mLayersWithQueuedFrames:有 LayerFE 的层按所属 layerStack 分到主线程或卸载 args;若 release fence promise 还没建或已用完,给未上屏层挂上 UNASSIGNED 的 future。
for (auto& [layer, _] : mLayersWithQueuedFrames) {
if (const auto& layerFE =
layer->getCompositionEngineLayerFE({static_cast<uint32_t>(layer->sequence)})) {
if (!optionalOffloadedRefreshArgs ||
(layerFE->mSnapshot != nullptr &&
layerFE->mSnapshot->outputFilter.layerStack != ui::UNASSIGNED_LAYER_STACK &&
mainThreadLayerStacks.count(layerFE->mSnapshot->outputFilter.layerStack.id))) {
mainThreadRefreshArgs.layersWithQueuedFrames.push_back(layerFE);
} else {
optionalOffloadedRefreshArgs->layersWithQueuedFrames.push_back(layerFE);
}
// Some layers are not displayed and do not yet have a future release fence
if (layerFE->getReleaseFencePromiseStatus() ==
LayerFE::ReleaseFencePromiseStatus::UNINITIALIZED ||
layerFE->getReleaseFencePromiseStatus() ==
LayerFE::ReleaseFencePromiseStatus::FULFILLED) {
// layerStack is unassigned because layer is not on a display
attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(),
ui::UNASSIGNED_LAYER_STACK);
}
}
}
//有卸载 args 则异步启动 GPU 合成,拿到 future,主线程可并行做 HWC present。
std::optional<std::future<void>> offloadedCompositionFuture;
if (optionalOffloadedRefreshArgs) {
offloadedCompositionFuture =
offloadGpuCompositedDisplays(std::move(*optionalOffloadedRefreshArgs),
offloadedLayers);
}
//合成核心:CompositionEngine 对主线程 outputs 做 validate → 选 HWC/GPU 策略 → RenderEngine / Composer HAL present。
mCompositionEngine->present(mainThreadRefreshArgs);
//present 后收尾 readback。
finalizeReadback(mainThreadRefreshArgs.outputs);
//本帧有几何 / 可见区域更新 → ADPF 标记 VISIBLE_REGION。
ftl::Flags<adpf::Workload> compositedWorkload;
if (mainThreadRefreshArgs.updatingGeometryThisFrame ||
mainThreadRefreshArgs.updatingOutputGeometryThisFrame) {
compositedWorkload |= adpf::Workload::VISIBLE_REGION;
}
if (mFrontEndDisplayInfosChanged) {
compositedWorkload |= adpf::Workload::DISPLAY_CHANGES;
SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Display Changes");
}
ftl::StaticVector<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary;
auto lastLayerStack = ui::UNASSIGNED_LAYER_STACK;
//遍历主线程 layers:stealCompositionResult() 取回本层合成结果;按 layerStack 用空格分隔;用 [...] 标 HWC cached set;单字符描述每层是 GPU 大写 / DPU 小写 / 特效等;有 effect 则加 EFFECTS;有 client composition fence 则记回 Layer;可选 picture profile 追踪。
uint64_t prevOverrideBufferId = 0;
for (auto& [layer, layerFE] : layers) {
CompositionResult compositionResult{layerFE->stealCompositionResult()};
if (lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
if (lastLayerStack != ui::UNASSIGNED_LAYER_STACK) {
// add a space to separate displays
compositionSummary.push_back(' ');
}
lastLayerStack = layerFE->mSnapshot->outputFilter.layerStack;
}
// If there are N layers in a cached set they should all share the same buffer id.
// The first layer in the cached set will be not skipped and layers 1..N-1 will be skipped.
// We expect all layers in the cached set to be marked as composited by HWC.
// Here is a made up example of how it is visualized
//
// [b:rrc][s:cc]
//
// This should be interpreted to mean that there are 2 cached sets.
// So there are only 2 non skipped layers -- b and s.
// The layers rrc and cc are flattened into layers b and s respectively.
const LayerFE::HwcLayerDebugState& hwcState = layerFE->getLastHwcState();
if (hwcState.overrideBufferId != prevOverrideBufferId) {
// End the existing run.
if (prevOverrideBufferId) {
compositionSummary.push_back(']');
}
// Start a new run.
if (hwcState.overrideBufferId) {
compositionSummary.push_back('[');
}
}
compositionSummary.push_back(layerFE->mSnapshot->classifyCompositionForDebug(hwcState));
if (hwcState.overrideBufferId && !hwcState.wasSkipped) {
compositionSummary.push_back(':');
}
prevOverrideBufferId = hwcState.overrideBufferId;
if (layerFE->mSnapshot->hasEffect()) {
compositedWorkload |= adpf::Workload::EFFECTS;
}
if (compositionResult.lastClientCompositionFence) {
layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
}
if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
mActivePictureTracker.onLayerComposed(*layer, *layerFE, compositionResult);
}
}
// End the last run.
if (prevOverrideBufferId) {
compositionSummary.push_back(']');
}
// Concisely describe the layers composited this frame using single chars. GPU composited layers
// are uppercase, DPU composited are lowercase. Special chars denote effects (blur, shadow,
// etc.). This provides a snapshot of the compositing workload.
SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
ftl::Concat("Layers: ", layers.size(), " ",
ftl::truncated<WorkloadTracer::COMPOSITION_SUMMARY_SIZE>(
std::string_view(compositionSummary.begin(),
compositionSummary.size())))
.c_str());
//把工作负载交给 PowerAdvisor,结束 Composition 异步 trace。
mPowerAdvisor->setCompositedWorkload(compositedWorkload);
SFTRACE_ASYNC_FOR_TRACK_END(WorkloadTracer::TRACK_NAME,
WorkloadTracer::COMPOSITION_TRACE_COOKIE);
SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Post Composition");
SFTRACE_NAME("postComposition");
//支持 HDCP 时:非 secure 屏上却有 secure layer → 启动 HDCP 协商。
if (mDisplayModeController.supportsHdcp()) {
for (const auto& [id, _] : frameTargeters) {
ftl::FakeGuard guard(mStateLock);
if (const auto display = getCompositionDisplayLocked(id)) {
if (!display->isSecure() && display->hasSecureLayers()) {
mDisplayModeController.startHdcpNegotiation(id);
}
}
}
}
moveSnapshotsFromCompositionArgs(mainThreadRefreshArgs, layers); //把主线程 args 里的 snapshot 所有权挪回 Layer(避免 CompositionEngine 持有过久)。
if (optionalOffloadedRefreshArgs) { //等卸载合成完成,再同样归还 snapshot。
offloadedCompositionFuture->wait();
moveSnapshotsFromCompositionArgs(*optionalOffloadedRefreshArgs, offloadedLayers);
}
mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime());//记录本帧从 frameBeginTime 到现在的 duration。
// Send a power hint after presentation is finished.
if (mPowerHintSessionEnabled) {
// Now that the current frame has been presented above, PowerAdvisor needs the present time
// of the previous frame (whose fence is signaled by now) to determine how long the HWC had
// waited on that fence to retire before presenting.
// TODO(b/355238809) `presentFenceForPreviousFrame` might not always be signaled (e.g. on
// devices
// where HWC does not block on the previous present fence). Revise this assumtion.
const auto& previousPresentFence = pacesetterTarget.presentFenceForPreviousFrame();
mPowerAdvisor->setSfPresentTiming(TimePoint::fromNs(previousPresentFence->getSignalTime()),
TimePoint::now());
mPowerAdvisor->reportActualWorkDuration();
}
//通知 Scheduler "合成已 present";若它要求再合成一帧,则 scheduleComposite。
if (mScheduler->onCompositionPresented(presentTime)) {
scheduleComposite(FrameHint::kNone);
}
//重置 expected present hint 状态,并走 onCompositionPresented(更新各屏 fence、延迟等)。
mNotifyExpectedPresentMap[pacesetterId].hintStatus = NotifyExpectedPresentHintStatus::Start;
onCompositionPresented(pacesetterId, frameTargeters, presentTime);
//记住上一帧是否用过 GPU 合成,然后清空本帧 coverage 表。
const bool hadGpuComposited =
multiDisplayUnion(mCompositionCoverage).test(CompositionCoverage::Gpu);
mCompositionCoverage.clear();
TimeStats::ClientCompositionRecord clientCompositionRecord;
//按每屏 CompositionDisplay state:标 HWC / GpuReuse / Gpu,并统计策略预测是否启用/成功。
for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
const auto& state = display->getCompositionDisplay()->getState();
CompositionCoverageFlags& flags =
mCompositionCoverage.try_emplace(display->getDisplayIdVariant()).first->second;
if (state.usesDeviceComposition) {
flags |= CompositionCoverage::Hwc;
}
if (state.reusedClientComposition) {
flags |= CompositionCoverage::GpuReuse;
} else if (state.usesClientComposition) {
flags |= CompositionCoverage::Gpu;
}
clientCompositionRecord.predicted |=
(state.strategyPrediction != CompositionStrategyPredictionState::DISABLED);
clientCompositionRecord.predictionSucceeded |=
(state.strategyPrediction == CompositionStrategyPredictionState::SUCCESS);
}
const auto coverage = multiDisplayUnion(mCompositionCoverage);
const bool hasGpuComposited = coverage.test(CompositionCoverage::Gpu);
clientCompositionRecord.hadClientComposition = hasGpuComposited;
clientCompositionRecord.reused = coverage.test(CompositionCoverage::GpuReuse);
clientCompositionRecord.changed = hadGpuComposited != hasGpuComposited;
mTimeStats->pushCompositionStrategyState(clientCompositionRecord);
using namespace ftl::flag_operators;
//本帧有 GPU 合成或 reuse → 通知 VsyncModulator(可拉长/调整 SF 工作窗口)。
// TODO(b/160583065): Enable skip validation when SF caches all client composition layers.
const bool hasGpuUseOrReuse =
coverage.any(CompositionCoverage::Gpu | CompositionCoverage::GpuReuse);
mScheduler->modulateVsync({}, &VsyncModulator::onDisplayRefresh, hasGpuUseOrReuse);
//清空"有排队帧"的层集合(本帧已消费)。
mLayersWithQueuedFrames.clear();
doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
vsyncId);
//把本帧 vsync / 时间同步给 InputFlinger。
updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
//可见区域曾脏则标 HDR 层信息需更新,并清 mVisibleRegionsDirty。
if (mVisibleRegionsDirty) mHdrLayerInfoChanged = true;
mVisibleRegionsDirty = false;
//CompositionEngine 若还要再更新(如某些异步路径)→ 再 schedule 一次 commit。
if (mCompositionEngine->needsAnotherUpdate()) {
scheduleCommit(FrameHint::kNone);
}
if (mPowerHintSessionEnabled) {
mPowerAdvisor->setCompositeEnd(TimePoint::now());
}
CompositeResultsPerDisplay resultsPerDisplay;
// Filter out virtual displays.
for (const auto& [idVar, coverage] : mCompositionCoverage) {
if (const auto idOpt = asPhysicalDisplayId(idVar)) {
resultsPerDisplay.try_emplace(*idOpt, CompositeResult{coverage});
}
}
//返回给 Scheduler;调用方会对每个 targeter 调 endFrame。
return resultsPerDisplay;
}


cpp
void CompositionEngine::present(CompositionRefreshArgs& args) {
SFTRACE_CALL();
ALOGV(__FUNCTION__);
preComposition(args);
{
// latchedLayers is used to track the set of front-end layer state that
// has been latched across all outputs for the prepare step, and is not
// needed for anything else.
LayerFESet latchedLayers;
for (const auto& output : args.outputs) {
output->prepare(args, latchedLayers);
}
}
// Offloading the HWC call for `present` allows us to simultaneously call it
// on multiple displays. This is desirable because these calls block and can
// be slow.
offloadOutputs(args.outputs);
ui::DisplayVector<ftl::Future<std::monostate>> presentFutures;
for (const auto& output : args.outputs) {
//这里有关送显
presentFutures.push_back(output->present(args));
}
{
SFTRACE_NAME("Waiting on HWC");
for (auto& future : presentFutures) {
// TODO(b/185536303): Call ftl::Future::wait() once it exists, since
// we do not need the return value of get().
future.get();
}
}
postComposition(args);
}
void CompositionEngine::postComposition(CompositionRefreshArgs& args) {
SFTRACE_CALL();
ALOGV(__FUNCTION__);
const bool force_slower_follower_gpu_composition =
FlagManager::getInstance().force_slower_follower_gpu_composition();
for (auto& layerFE : args.layers) {
if (layerFE->getReleaseFencePromiseStatus() ==
LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
if (force_slower_follower_gpu_composition) {
layerFE->setReleaseFence(layerFE->getAndClearLastClientTargetAcquireFence());
} else {
layerFE->setReleaseFence(Fence::NO_FENCE);
}
}
}
// List of layersWithQueuedFrames does not necessarily overlap with
// list of layers, so those layersWithQueuedFrames also need any
// unfulfilled promises to be resolved for completeness.
for (auto& layerFE : args.layersWithQueuedFrames) {
if (layerFE->getReleaseFencePromiseStatus() ==
LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
if (force_slower_follower_gpu_composition) {
layerFE->setReleaseFence(layerFE->getAndClearLastClientTargetAcquireFence());
} else {
layerFE->setReleaseFence(Fence::NO_FENCE);
}
}
}
}