android 图形学之图层数据送显(八)

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);
            }
        }
    }
}
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui