AOSP android 15 Surfaceflinger 部分源码

surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    capabilities SYS_NICE
    onrestart restart --only-if-running zygote
    task_profiles HighPerformance
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0


main(main_surfaceflinger.cpp)

int main(int, char**) {
    signal(SIGPIPE, SIG_IGN);

    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);

    startGraphicsAllocatorService();

    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    // Set uclamp.min setting on all threads, maybe an overkill but we want
    // to cover important threads like RenderEngine.
    if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
        ALOGW("Failed to set uclamp.min during boot: %s", strerror(errno));
    }

    // The binder threadpool we start will inherit sched policy and priority
    // of (this) creating thread. We want the binder thread pool to have
    // SCHED_FIFO policy and priority 1 (lowest RT priority)
    // Once the pool is created we reset this thread's priority back to
    // original.
    int newPriority = 0;
    int origPolicy = sched_getscheduler(0);
    struct sched_param origSchedParam;

    int errorInPriorityModification = sched_getparam(0, &origSchedParam);
    if (errorInPriorityModification == 0) {
        int policy = SCHED_FIFO;
        newPriority = sched_get_priority_min(policy);

        struct sched_param param;
        param.sched_priority = newPriority;

        errorInPriorityModification = sched_setscheduler(0, policy, &param);
    }

    // start the thread pool
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();

    // Reset current thread's policy and priority
    if (errorInPriorityModification == 0) {
        errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam);
    } else {
        ALOGE("Failed to set SurfaceFlinger binder threadpool priority to SCHED_FIFO");
    }

    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();

    // Set the minimum policy of surfaceflinger node to be SCHED_FIFO.
    // So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run
    // at least with SCHED_FIFO policy and priority 1.
    if (errorInPriorityModification == 0) {
        flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
    }

    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);

    set_sched_policy(0, SP_FOREGROUND);

    // initialize before clients can connect
    flinger->init();

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

    // publish gui::ISurfaceComposer, the new AIDL interface
    sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
    if (FlagManager::getInstance().misc1()) {
        composerAIDL->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
    }
    sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

    startDisplayService(); // dependency on SF getting registered above

    if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
        ALOGW("Failed to set SCHED_FIFO during boot: %s", strerror(errno));
    }

    // run surface flinger in this thread
    flinger->run();

    return 0;
}

SurfaceFlinger::init

void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    ATRACE_CALL();
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");
    addTransactionReadyFilters();
    Mutex::Autolock lock(mStateLock);

    // Get a RenderEngine for the given display / config (can't fail)
    // TODO(b/77156734): We need to stop casting and use HAL types when possible.
    // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
    auto builder = renderengine::RenderEngineCreationArgs::Builder()
                           .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
                           .setImageCacheSize(maxFrameBufferAcquiredBuffers)
                           .setEnableProtectedContext(enable_protected_contents(false))
                           .setPrecacheToneMapperShaderOnly(false)
                           .setBlurAlgorithm(chooseBlurAlgorithm(mSupportsBlur))
                           .setContextPriority(
                                   useContextPriority
                                           ? renderengine::RenderEngine::ContextPriority::REALTIME
                                           : renderengine::RenderEngine::ContextPriority::MEDIUM);
    chooseRenderEngineType(builder);
    mRenderEngine = renderengine::RenderEngine::create(builder.build());
    mCompositionEngine->setRenderEngine(mRenderEngine.get());
    mMaxRenderTargetSize =
            std::min(getRenderEngine().getMaxTextureSize(), getRenderEngine().getMaxViewportDims());

    // Set SF main policy after initializing RenderEngine which has its own policy.
    if (!SetTaskProfiles(0, {"SFMainPolicy"})) {
        ALOGW("Failed to set main task profile");
    }

    mCompositionEngine->setTimeStats(mTimeStats);

    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    auto& composer = mCompositionEngine->getHwComposer();
    composer.setCallback(*this);
    mDisplayModeController.setHwComposer(&composer);

    ClientCache::getInstance().setRenderEngine(&getRenderEngine());

    mHasReliablePresentFences =
            !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE);

    enableLatchUnsignaledConfig = getLatchUnsignaledConfig();

    if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) {
        enableHalVirtualDisplays(true);
    }

    // Process hotplug for displays connected at boot.
    LOG_ALWAYS_FATAL_IF(!configureLocked(),
                        "Initial display configuration failed: HWC did not hotplug");

    // Commit primary display.
    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();
    }

    LOG_ALWAYS_FATAL_IF(!display, "Failed to configure the primary display");
    LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getPhysicalId()),
                        "Primary display is disconnected");

    // TODO(b/241285876): The Scheduler needlessly depends on creating the CompositionEngine part of
    // the DisplayDevice, hence the above commit of the primary display. Remove that special case by
    // initializing the Scheduler after configureLocked, once decoupled from DisplayDevice.
    initScheduler(display);

    // Start listening after creating the Scheduler, since the listener calls into it.
    mDisplayModeController.setActiveModeListener(
            display::DisplayModeController::ActiveModeListener::make(
                    [this](PhysicalDisplayId displayId, Fps vsyncRate, Fps renderRate) {
                        // This callback cannot lock mStateLock, as some callers already lock it.
                        // Instead, switch context to the main thread.
                        static_cast<void>(mScheduler->schedule([=,
                                                                this]() FTL_FAKE_GUARD(mStateLock) {
                            if (const auto display = getDisplayDeviceLocked(displayId)) {
                                display->updateRefreshRateOverlayRate(vsyncRate, renderRate);
                            }
                        }));
                    }));

    mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) {
        auto snapshot = perfetto::protos::LayersSnapshotProto{};
        mScheduler
                ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
                    snapshot = takeLayersSnapshotProto(traceFlags, TimePoint::now(),
                                                       mLastCommittedVsyncId, true);
                })
                .wait();
        return snapshot;
    });

    // Commit secondary display(s).
    processDisplayChangesLocked();

    // initialize our drawing state
    mDrawingState = mCurrentState;

    onActiveDisplayChangedLocked(nullptr, *display);

    static_cast<void>(mScheduler->schedule(
            [this]() FTL_FAKE_GUARD(kMainThreadContext) { initializeDisplays(); }));

    mPowerAdvisor->init();

    if (base::GetBoolProperty("service.sf.prime_shader_cache"s, true)) {
        if (setSchedFifo(false) != NO_ERROR) {
            ALOGW("Can't set SCHED_OTHER for primeCache");
        }

        mRenderEnginePrimeCacheFuture.callOnce([this] {
            renderengine::PrimeCacheConfig config;
            config.cacheHolePunchLayer =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.hole_punch"s, true);
            config.cacheSolidLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.solid_layers"s, true);
            config.cacheSolidDimmedLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.solid_dimmed_layers"s, true);
            config.cacheImageLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.image_layers"s, true);
            config.cacheImageDimmedLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.image_dimmed_layers"s, true);
            config.cacheClippedLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.clipped_layers"s, true);
            config.cacheShadowLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.shadow_layers"s, true);
            config.cachePIPImageLayers =
                    base::GetBoolProperty("debug.sf.prime_shader_cache.pip_image_layers"s, true);
            config.cacheTransparentImageDimmedLayers = base::
                    GetBoolProperty("debug.sf.prime_shader_cache.transparent_image_dimmed_layers"s,
                                    true);
            config.cacheClippedDimmedImageLayers = base::
                    GetBoolProperty("debug.sf.prime_shader_cache.clipped_dimmed_image_layers"s,
                                    true);
            // ro.surface_flinger.prime_chader_cache.ultrahdr exists as a previous ro property
            // which we maintain for backwards compatibility.
            config.cacheUltraHDR =
                    base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false);
            return getRenderEngine().primeCache(config);
        });

        if (setSchedFifo(true) != NO_ERROR) {
            ALOGW("Can't set SCHED_FIFO after primeCache");
        }
    }

    // Avoid blocking the main thread on `init` to set properties.
    mInitBootPropsFuture.callOnce([this] {
        return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this);
    });

    initTransactionTraceWriter();
    ALOGV("Done initializing");
}

Scheduler::onFrameSignal

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

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

    {
        FrameTargets targets;
        targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target());

        // TODO (b/256196556): Followers should use the next VSYNC after the frontrunner, not the
        // pacesetter.
        // Update expectedVsyncTime, which may have been adjusted by beginFrame.
        expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime();

        for (const auto& [id, display] : mDisplays) {
            if (id == pacesetterPtr->displayId) continue;

            auto followerBeginFrameArgs = beginFrameArgs;
            followerBeginFrameArgs.expectedVsyncTime =
                    display.schedulePtr->vsyncDeadlineAfter(expectedVsyncTime);

            FrameTargeter& targeter = *display.targeterPtr;
            targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr);
            targets.try_emplace(id, &targeter.target());
        }

        if (!compositor.commit(pacesetterPtr->displayId, targets)) {
            if (FlagManager::getInstance().vrr_config()) {
                compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
            }
            mSchedulerCallback.onCommitNotComposited(pacesetterPtr->displayId);
            return;
        }
    }

    // The pacesetter may have changed or been registered anew during commit.
    pacesetterPtr = pacesetterPtrLocked();

    // TODO(b/256196556): Choose the frontrunner display.
    FrameTargeters targeters;
    targeters.try_emplace(pacesetterPtr->displayId, pacesetterPtr->targeterPtr.get());

    for (auto& [id, display] : mDisplays) {
        if (id == pacesetterPtr->displayId) continue;

        FrameTargeter& targeter = *display.targeterPtr;
        targeters.try_emplace(id, &targeter);
    }

    if (FlagManager::getInstance().vrr_config() &&
        CC_UNLIKELY(mPacesetterFrameDurationFractionToSkip > 0.f)) {
        const auto period = pacesetterPtr->targeterPtr->target().expectedFrameDuration();
        const auto skipDuration = Duration::fromNs(
                static_cast<nsecs_t>(period.ns() * mPacesetterFrameDurationFractionToSkip));
        ATRACE_FORMAT("Injecting jank for %f%% of the frame (%" PRId64 " ns)",
                      mPacesetterFrameDurationFractionToSkip * 100, skipDuration.ns());
        std::this_thread::sleep_for(skipDuration);
        mPacesetterFrameDurationFractionToSkip = 0.f;
    }

    const auto resultsPerDisplay = compositor.composite(pacesetterPtr->displayId, targeters);
    if (FlagManager::getInstance().vrr_config()) {
        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);
    }
}

SurfaceFlinger::commit

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

    const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());

    if (pacesetterFrameTarget.didMissFrame()) {
        mTimeStats->incrementMissedFrames();
    }

    // If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
    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;
    }

    {
        ConditionalLock lock(mStateLock, FlagManager::getInstance().connected_display());

        for (const auto [displayId, _] : frameTargets) {
            if (mDisplayModeController.isModeSetPending(displayId)) {
                finalizeDisplayModeChange(displayId);
            }
        }
    }

    if (pacesetterFrameTarget.isFramePending()) {
        if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
            if (FlagManager::getInstance().vrr_config()) {
                mScheduler->getVsyncSchedule()->getTracker().onFrameMissed(
                        pacesetterFrameTarget.expectedPresentTime());
            }
            scheduleCommit(FrameHint::kNone);
            return false;
        }
    }

    const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();

    // Save this once per commit + composite to ensure consistency
    // TODO (b/240619471): consider removing active display check once AOD is fixed
    const auto activeDisplay = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(mActiveDisplayId));
    mPowerHintSessionEnabled = mPowerAdvisor->usePowerHintSession() && activeDisplay &&
            activeDisplay->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();

        mPowerAdvisor->setFrameDelay(frameDelay);
        mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);

        const Period idealVsyncPeriod =
                mDisplayModeController.getActiveMode(pacesetterId).fps.getPeriod();
        mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod);
    }

    if (mRefreshRateOverlaySpinner || mHdrSdrRatioOverlay) {
        Mutex::Autolock lock(mStateLock);
        if (const auto display = getDefaultDisplayDeviceLocked()) {
            display->animateOverlay();
        }
    }

    // Composite if transactions were committed, or if requested by HWC.
    bool mustComposite = mMustComposite.exchange(false);
    {
        mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId),
                                    pacesetterFrameTarget.frameBeginTime().ns(),
                                    Fps::fromPeriodNsecs(vsyncPeriod.ns()),
                                    mScheduler->getPacesetterRefreshRate());

        const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
        bool transactionsAreEmpty = false;
        if (mLayerLifecycleManagerEnabled) {
            mustComposite |=
                    updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().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.
        if (FlagManager::getInstance().vrr_config() && 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.
            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
    {
        bool updateAttachedChoreographer = mUpdateAttachedChoreographer;
        mUpdateAttachedChoreographer = false;

        Mutex::Autolock lock(mStateLock);
        mScheduler->chooseRefreshRateForContent(mLayerLifecycleManagerEnabled
                                                        ? &mLayerHierarchyBuilder.getHierarchy()
                                                        : nullptr,
                                                updateAttachedChoreographer);

        if (FlagManager::getInstance().connected_display()) {
            initiateDisplayModeChanges();
        }
    }

    if (!FlagManager::getInstance().connected_display()) {
        ftl::FakeGuard guard(mStateLock);
        initiateDisplayModeChanges();
    }

    updateCursorAsync();
    if (!mustComposite) {
        updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime());
    }
    doActiveLayersTracingIfNeeded(false, mVisibleRegionsDirty,
                                  pacesetterFrameTarget.frameBeginTime(), vsyncId);

    mLastCommittedVsyncId = vsyncId;

    persistDisplayBrightness(mustComposite);

    return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}

SurfaceFlinger::composite

CompositeResultsPerDisplay SurfaceFlinger::composite(
        PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
    const scheduler::FrameTarget& pacesetterTarget =
            frameTargeters.get(pacesetterId)->get()->target();

    const VsyncId vsyncId = pacesetterTarget.vsyncId();
    ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());

    compositionengine::CompositionRefreshArgs refreshArgs;
    refreshArgs.powerCallback = this;
    const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
    refreshArgs.outputs.reserve(displays.size());

    // Add outputs for physical displays.
    for (const auto& [id, targeter] : frameTargeters) {
        ftl::FakeGuard guard(mStateLock);

        if (const auto display = getCompositionDisplayLocked(id)) {
            refreshArgs.outputs.push_back(display);
        }

        refreshArgs.frameTargets.try_emplace(id, &targeter->target());
    }

    std::vector<DisplayId> displayIds;
    for (const auto& [_, display] : displays) {
        displayIds.push_back(display->getId());
        display->tracePowerMode();

        // Add outputs for virtual displays.
        if (display->isVirtual()) {
            const Fps refreshRate = display->getAdjustedRefreshRate();

            if (!refreshRate.isValid() ||
                mScheduler->isVsyncInPhase(pacesetterTarget.frameBeginTime(), refreshRate)) {
                refreshArgs.outputs.push_back(display->getCompositionDisplay());
            }
        }
    }
    mPowerAdvisor->setDisplays(displayIds);

    const bool updateTaskMetadata = mCompositionEngine->getFeatureFlags().test(
            compositionengine::Feature::kSnapshotLayerMetadata);
    if (updateTaskMetadata && (mVisibleRegionsDirty || mLayerMetadataSnapshotNeeded)) {
        updateLayerMetadataSnapshot();
        mLayerMetadataSnapshotNeeded = false;
    }

    refreshArgs.bufferIdsToUncache = std::move(mBufferIdsToUncache);

    if (!FlagManager::getInstance().ce_fence_promise()) {
        refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
        for (auto& layer : mLayersWithQueuedFrames) {
            if (const auto& layerFE = layer->getCompositionEngineLayerFE())
                refreshArgs.layersWithQueuedFrames.push_back(layerFE);
        }
    }

    refreshArgs.outputColorSetting = mDisplayColorSetting;
    refreshArgs.forceOutputColorMode = mForceColorMode;

    refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
    refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) ||
            mVisibleRegionsDirty || mDrawingState.colorMatrixChanged;
    refreshArgs.internalDisplayRotationFlags = getActiveDisplayRotationFlags();

    if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
        refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
        mDrawingState.colorMatrixChanged = false;
    }

    refreshArgs.devOptForceClientComposition = mDebugDisableHWC;

    if (mDebugFlashDelay != 0) {
        refreshArgs.devOptForceClientComposition = true;
        refreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::milliseconds(mDebugFlashDelay);
    }

    // TODO(b/255601557) Update frameInterval per display
    refreshArgs.frameInterval =
            mScheduler->getNextFrameInterval(pacesetterId, pacesetterTarget.expectedPresentTime());
    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();

    constexpr bool kCursorOnly = false;
    const auto layers = moveSnapshotsToCompositionArgs(refreshArgs, kCursorOnly);

    if (mLayerLifecycleManagerEnabled && !mVisibleRegionsDirty) {
        for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
            auto compositionDisplay = display->getCompositionDisplay();
            if (!compositionDisplay->getState().isEnabled) continue;
            for (auto outputLayer : compositionDisplay->getOutputLayersOrderedByZ()) {
                if (outputLayer->getLayerFE().getCompositionState() == nullptr) {
                    // This is unexpected but instead of crashing, capture traces to disk
                    // and recover gracefully by forcing CE to rebuild layer stack.
                    ALOGE("Output layer %s for display %s %" PRIu64 " has a null "
                          "snapshot. Forcing mVisibleRegionsDirty",
                          outputLayer->getLayerFE().getDebugName(),
                          compositionDisplay->getName().c_str(), compositionDisplay->getId().value);

                    TransactionTraceWriter::getInstance().invoke(__func__, /* overwrite= */ false);
                    mVisibleRegionsDirty = true;
                    refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
                    refreshArgs.updatingGeometryThisFrame = mVisibleRegionsDirty;
                }
            }
        }
    }

    refreshArgs.refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
    for (auto& [layer, layerFE] : layers) {
        layer->onPreComposition(refreshArgs.refreshStartTime);
    }

    if (FlagManager::getInstance().ce_fence_promise()) {
        for (auto& [layer, layerFE] : layers) {
            attachReleaseFenceFutureToLayer(layer, layerFE,
                                            layerFE->mSnapshot->outputFilter.layerStack);
        }

        refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
        for (auto& layer : mLayersWithQueuedFrames) {
            if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
                refreshArgs.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 invalid because layer is not on a display
                    attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(),
                                                    ui::INVALID_LAYER_STACK);
                }
            }
        }

        mCompositionEngine->present(refreshArgs);
        moveSnapshotsFromCompositionArgs(refreshArgs, layers);

        for (auto& [layer, layerFE] : layers) {
            CompositionResult compositionResult{layerFE->stealCompositionResult()};
            if (compositionResult.lastClientCompositionFence) {
                layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
            }
        }

    } else {
        mCompositionEngine->present(refreshArgs);
        moveSnapshotsFromCompositionArgs(refreshArgs, layers);

        for (auto [layer, layerFE] : layers) {
            CompositionResult compositionResult{layerFE->stealCompositionResult()};
            for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) {
                Layer* clonedFrom = layer->getClonedFrom().get();
                auto owningLayer = clonedFrom ? clonedFrom : layer;
                owningLayer->onLayerDisplayed(std::move(releaseFence), layerStack);
            }
            if (compositionResult.lastClientCompositionFence) {
                layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
            }
        }
    }

    mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime());

    // 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.
        const auto& previousPresentFence = pacesetterTarget.presentFenceForPreviousFrame();

        mPowerAdvisor->setSfPresentTiming(TimePoint::fromNs(previousPresentFence->getSignalTime()),
                                          TimePoint::now());
        mPowerAdvisor->reportActualWorkDuration();
    }

    if (mScheduler->onCompositionPresented(presentTime)) {
        scheduleComposite(FrameHint::kNone);
    }

    mNotifyExpectedPresentMap[pacesetterId].hintStatus = NotifyExpectedPresentHintStatus::Start;
    onCompositionPresented(pacesetterId, frameTargeters, presentTime);

    const bool hadGpuComposited =
            multiDisplayUnion(mCompositionCoverage).test(CompositionCoverage::Gpu);
    mCompositionCoverage.clear();

    TimeStats::ClientCompositionRecord clientCompositionRecord;

    for (const auto& [_, display] : displays) {
        const auto& state = display->getCompositionDisplay()->getState();
        CompositionCoverageFlags& flags =
                mCompositionCoverage.try_emplace(display->getId()).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;

    // 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();
    mLayersIdsWithQueuedFrames.clear();
    doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
                                  vsyncId);

    updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());

    if (mVisibleRegionsDirty) mHdrLayerInfoChanged = true;
    mVisibleRegionsDirty = false;

    if (mCompositionEngine->needsAnotherUpdate()) {
        scheduleCommit(FrameHint::kNone);
    }

    if (mPowerHintSessionEnabled) {
        mPowerAdvisor->setCompositeEnd(TimePoint::now());
    }

    CompositeResultsPerDisplay resultsPerDisplay;

    // Filter out virtual displays.
    for (const auto& [id, coverage] : mCompositionCoverage) {
        if (const auto idOpt = PhysicalDisplayId::tryCast(id)) {
            resultsPerDisplay.try_emplace(*idOpt, CompositeResult{coverage});
        }
    }

    return resultsPerDisplay;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容