Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0217956 authored by Melody Hsu's avatar Melody Hsu Committed by Android (Google) Code Review
Browse files

Merge changes Id6fdfc53,If9d4134a into main

* changes:
  Remove flag single_hop_screenshots
  Reorder release fence attachment for non-threaded RE
parents d74dfd0f 16c4c32c
Loading
Loading
Loading
Loading
+7 −16
Original line number Diff line number Diff line
@@ -353,22 +353,13 @@ void RegionSamplingThread::captureSample() {
                              sampledBounds.getSize(), ui::Dataspace::V0_SRGB, displayWeak,
                              RenderArea::Options::CAPTURE_SECURE_LAYERS);

    FenceResult fenceResult;
    if (FlagManager::getInstance().single_hop_screenshot() &&
        mFlinger.mRenderEngine->isThreaded()) {
        std::vector<sp<LayerFE>> layerFEs;
        auto displayState = mFlinger.getSnapshotsFromMainThread(renderAreaBuilder,
                                                                getLayerSnapshotsFn, layerFEs);
        fenceResult = mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling,
                                                 kGrayscale, kIsProtected, kAttachGainmap, nullptr,
                                                 displayState, layerFEs)
    std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
    auto displayState =
            mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
    FenceResult fenceResult =
            mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling, kGrayscale,
                                       kIsProtected, kAttachGainmap, nullptr, displayState, layers)
                    .get();
    } else {
        fenceResult = mFlinger.captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn,
                                                       buffer, kRegionSampling, kGrayscale,
                                                       kIsProtected, kAttachGainmap, nullptr)
                              .get();
    }
    if (fenceResult.ok()) {
        fenceResult.value()->waitForever(LOG_TAG);
    }
+75 −180
Original line number Diff line number Diff line
@@ -7158,9 +7158,10 @@ void SurfaceFlinger::attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* laye
// typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.
// A protected layer has no implication on whether it's secure, which is explicitly set by
// application to avoid being screenshot or drawn via unsecure display.
bool SurfaceFlinger::layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const {
bool SurfaceFlinger::layersHasProtectedLayer(
        const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
    bool protectedLayerFound = false;
    for (auto& layerFE : layers) {
    for (auto& [_, layerFE] : layers) {
        protectedLayerFound |=
                (layerFE->mSnapshot->isVisible && layerFE->mSnapshot->hasProtectedContent);
        if (protectedLayerFound) {
@@ -7176,15 +7177,21 @@ bool SurfaceFlinger::layersHasProtectedLayer(const std::vector<sp<LayerFE>>& lay
// risk of deadlocks.
std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getSnapshotsFromMainThread(
        RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
        std::vector<sp<LayerFE>>& layerFEs) {
        std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
    return mScheduler
            ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) {
            ->schedule([=, this, &renderAreaBuilder, &layers]() REQUIRES(kMainThreadContext) {
                SFTRACE_NAME("getSnapshotsFromMainThread");
                auto layers = getLayerSnapshotsFn();
                layers = getLayerSnapshotsFn();
                // Non-threaded RenderEngine eventually returns to the main thread a 2nd time
                // to complete the screenshot. Release fences should only be added during the 2nd
                // hop to main thread in order to avoid potential deadlocks from waiting for the
                // the future fence to fire.
                if (mRenderEngine->isThreaded()) {
                    for (auto& [layer, layerFE] : layers) {
                    attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
                        attachReleaseFenceFutureToLayer(layer, layerFE.get(),
                                                        ui::INVALID_LAYER_STACK);
                    }
                }
                layerFEs = extractLayerFEs(layers);
                return getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
            })
            .get();
@@ -7205,50 +7212,13 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil
        return;
    }

    if (FlagManager::getInstance().single_hop_screenshot() && mRenderEngine->isThreaded()) {
        std::vector<sp<LayerFE>> layerFEs;
        auto displayState =
                getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layerFEs);

        const bool supportsProtected = getRenderEngine().supportsProtectedContent();
        bool hasProtectedLayer = false;
        if (allowProtected && supportsProtected) {
            hasProtectedLayer = layersHasProtectedLayer(layerFEs);
        }
        const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
        const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
                GRALLOC_USAGE_HW_TEXTURE |
                (isProtected ? GRALLOC_USAGE_PROTECTED
                             : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
        sp<GraphicBuffer> buffer =
                getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
                                                 static_cast<android_pixel_format>(reqPixelFormat),
                                                 1 /* layerCount */, usage, "screenshot");

        const status_t bufferStatus = buffer->initCheck();
        if (bufferStatus != OK) {
            // Animations may end up being really janky, but don't crash here.
            // Otherwise an irreponsible process may cause an SF crash by allocating
            // too much.
            ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
            invokeScreenCaptureError(bufferStatus, captureListener);
            return;
        }
        const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
                renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
                                                     renderengine::impl::ExternalTexture::Usage::
                                                             WRITEABLE);
        auto futureFence = captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */,
                                             grayscale, isProtected, attachGainmap, captureListener,
                                             displayState, layerFEs);
        futureFence.get();
    std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
    auto displayState = getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);

    } else {
    const bool supportsProtected = getRenderEngine().supportsProtectedContent();
    bool hasProtectedLayer = false;
    if (allowProtected && supportsProtected) {
            auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get();
            hasProtectedLayer = layersHasProtectedLayer(extractLayerFEs(layers));
        hasProtectedLayer = layersHasProtectedLayer(layers);
    }
    const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
    const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
@@ -7273,12 +7243,11 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil
            renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
                                                 renderengine::impl::ExternalTexture::Usage::
                                                         WRITEABLE);
        auto futureFence = captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, texture,
                                                   false /* regionSampling */, grayscale,
                                                   isProtected, attachGainmap, captureListener);
    auto futureFence =
            captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */, grayscale,
                              isProtected, attachGainmap, captureListener, displayState, layers);
    futureFence.get();
}
}

std::optional<SurfaceFlinger::OutputCompositionState>
SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& renderAreaBuilder) {
@@ -7316,22 +7285,13 @@ SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& r
    return std::nullopt;
}

std::vector<sp<LayerFE>> SurfaceFlinger::extractLayerFEs(
        const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
    std::vector<sp<LayerFE>> layerFEs;
    layerFEs.reserve(layers.size());
    for (const auto& [_, layerFE] : layers) {
        layerFEs.push_back(layerFE);
    }
    return layerFEs;
}

ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
        const RenderAreaBuilderVariant& renderAreaBuilder,
        const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
        bool grayscale, bool isProtected, bool attachGainmap,
        const sp<IScreenCaptureListener>& captureListener,
        std::optional<OutputCompositionState>& displayState, std::vector<sp<LayerFE>>& layerFEs) {
        std::optional<OutputCompositionState>& displayState,
        std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
    SFTRACE_CALL();

    ScreenCaptureResults captureResults;
@@ -7350,11 +7310,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
    float displayBrightnessNits = displayState.value().displayBrightnessNits;
    float sdrWhitePointNits = displayState.value().sdrWhitePointNits;

    // Empty vector needed to pass into renderScreenImpl for legacy path
    std::vector<std::pair<Layer*, sp<android::LayerFE>>> layers;
    ftl::SharedFuture<FenceResult> renderFuture =
            renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
                             attachGainmap, captureResults, displayState, layers, layerFEs);
                             captureResults, displayState, layers);

    if (captureResults.capturedHdrLayers && attachGainmap &&
        FlagManager::getInstance().true_hdr_screenshots()) {
@@ -7389,8 +7347,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
            ScreenCaptureResults unusedResults;
            ftl::SharedFuture<FenceResult> hdrRenderFuture =
                    renderScreenImpl(renderArea.get(), hdrTexture, regionSampling, grayscale,
                                     isProtected, attachGainmap, unusedResults, displayState,
                                     layers, layerFEs);
                                     isProtected, unusedResults, displayState, layers);

            renderFuture =
                    ftl::Future(std::move(renderFuture))
@@ -7436,75 +7393,14 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
    return renderFuture;
}

ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshotLegacy(
        RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
        const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
        bool grayscale, bool isProtected, bool attachGainmap,
        const sp<IScreenCaptureListener>& captureListener) {
    SFTRACE_CALL();

    auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
                                    kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
        auto layers = getLayerSnapshotsFn();
        for (auto& [layer, layerFE] : layers) {
            attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
        }
        auto displayState = getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);

        ScreenCaptureResults captureResults;
        std::unique_ptr<const RenderArea> renderArea =
                std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
                           renderAreaBuilder);

        if (!renderArea) {
            ALOGW("Skipping screen capture because of invalid render area.");
            if (captureListener) {
                captureResults.fenceResult = base::unexpected(NO_MEMORY);
                captureListener->onScreenCaptureCompleted(captureResults);
            }
            return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
        }

        auto layerFEs = extractLayerFEs(layers);
        ftl::SharedFuture<FenceResult> renderFuture =
                renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
                                 attachGainmap, captureResults, displayState, layers, layerFEs);

        if (captureListener) {
            // Defer blocking on renderFuture back to the Binder thread.
            return ftl::Future(std::move(renderFuture))
                    .then([captureListener, captureResults = std::move(captureResults)](
                                  FenceResult fenceResult) mutable -> FenceResult {
                        captureResults.fenceResult = std::move(fenceResult);
                        captureListener->onScreenCaptureCompleted(captureResults);
                        return base::unexpected(NO_ERROR);
                    })
                    .share();
        }
        return renderFuture;
    };

    // TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number
    // of calls on the main thread.
    auto future =
            mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));

    // Flatten nested futures.
    auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
        return future;
    });

    return chain.share();
}

ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
        const RenderArea* renderArea, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
        bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
        ScreenCaptureResults& captureResults, std::optional<OutputCompositionState>& displayState,
        std::vector<std::pair<Layer*, sp<LayerFE>>>& layers, std::vector<sp<LayerFE>>& layerFEs) {
        bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
        std::optional<OutputCompositionState>& displayState,
        std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
    SFTRACE_CALL();

    for (auto& layerFE : layerFEs) {
    for (auto& [_, layerFE] : layers) {
        frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get();
        captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure);
        captureResults.capturedHdrLayers |= isHdrLayer(*snapshot);
@@ -7563,29 +7459,32 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
    captureResults.buffer = capturedBuffer->getBuffer();

    ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK};
    if (!layerFEs.empty()) {
        const sp<LayerFE>& layerFE = layerFEs.back();
    if (!layers.empty()) {
        const sp<LayerFE>& layerFE = layers.back().second;
        layerStack = layerFE->getCompositionState()->outputFilter.layerStack;
    }

    auto copyLayerFEs = [&layerFEs]() {
        std::vector<sp<compositionengine::LayerFE>> ceLayerFEs;
        ceLayerFEs.reserve(layerFEs.size());
        for (const auto& layerFE : layerFEs) {
            ceLayerFEs.push_back(layerFE);
        }
        return ceLayerFEs;
    };

    auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace,
                    sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected,
                    layerFEs = copyLayerFEs(), layerStack, regionSampling,
                    layers = std::move(layers), layerStack, regionSampling,
                    renderArea = std::move(renderArea), renderIntent,
                    enableLocalTonemapping]() -> FenceResult {
        std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
                mFactory.createCompositionEngine();
        compositionEngine->setRenderEngine(mRenderEngine.get());

        std::vector<sp<compositionengine::LayerFE>> layerFEs;
        layerFEs.reserve(layers.size());
        for (auto& [layer, layerFE] : layers) {
            // Release fences were not yet added for non-threaded render engine. To avoid
            // deadlocks between main thread and binder threads waiting for the future fence
            // result, fences should be added to layers in the same hop onto the main thread.
            if (!mRenderEngine->isThreaded()) {
                attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
            }
            layerFEs.push_back(layerFE);
        }

        compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace,
                                                             .renderIntent = renderIntent};

@@ -7643,13 +7542,9 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
    //
    // TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call
    // to CompositionEngine::present.
    ftl::SharedFuture<FenceResult> presentFuture;
    if (FlagManager::getInstance().single_hop_screenshot() && mRenderEngine->isThreaded()) {
        presentFuture = ftl::yield(present()).share();
    } else {
        presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share()
                                                    : ftl::yield(present()).share();
    }
    ftl::SharedFuture<FenceResult> presentFuture = mRenderEngine->isThreaded()
            ? ftl::yield(present()).share()
            : mScheduler->schedule(std::move(present)).share();

    return presentFuture;
}
+7 −19
Original line number Diff line number Diff line
@@ -851,13 +851,14 @@ private:
    void attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* layerFE, ui::LayerStack layerStack);

    // Checks if a protected layer exists in a list of layers.
    bool layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const;
    bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;

    using OutputCompositionState = compositionengine::impl::OutputCompositionState;

    std::optional<OutputCompositionState> getSnapshotsFromMainThread(
            RenderAreaBuilderVariant& renderAreaBuilder,
            GetLayerSnapshotsFunction getLayerSnapshotsFn, std::vector<sp<LayerFE>>& layerFEs);
            GetLayerSnapshotsFunction getLayerSnapshotsFn,
            std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);

    void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
                             ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
@@ -866,32 +867,19 @@ private:
    std::optional<OutputCompositionState> getDisplayStateFromRenderAreaBuilder(
            RenderAreaBuilderVariant& renderAreaBuilder) REQUIRES(kMainThreadContext);

    // Legacy layer raw pointer is not safe to access outside the main thread.
    // Creates a new vector consisting only of LayerFEs, which can be safely
    // accessed outside the main thread.
    std::vector<sp<LayerFE>> extractLayerFEs(
            const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;

    ftl::SharedFuture<FenceResult> captureScreenshot(
            const RenderAreaBuilderVariant& renderAreaBuilder,
            const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
            bool grayscale, bool isProtected, bool attachGainmap,
            const sp<IScreenCaptureListener>& captureListener,
            std::optional<OutputCompositionState>& displayState,
            std::vector<sp<LayerFE>>& layerFEs);

    ftl::SharedFuture<FenceResult> captureScreenshotLegacy(
            RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
            const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
            bool grayscale, bool isProtected, bool attachGainmap,
            const sp<IScreenCaptureListener>&);
            std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);

    ftl::SharedFuture<FenceResult> renderScreenImpl(
            const RenderArea*, const std::shared_ptr<renderengine::ExternalTexture>&,
            bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
            ScreenCaptureResults&, std::optional<OutputCompositionState>& displayState,
            std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
            std::vector<sp<LayerFE>>& layerFEs);
            bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&,
            std::optional<OutputCompositionState>& displayState,
            std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);

    void readPersistentProperties();

+0 −2
Original line number Diff line number Diff line
@@ -153,7 +153,6 @@ void FlagManager::dump(std::string& result) const {
    DUMP_READ_ONLY_FLAG(override_trusted_overlay);
    DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache);
    DUMP_READ_ONLY_FLAG(force_compile_graphite_renderengine);
    DUMP_READ_ONLY_FLAG(single_hop_screenshot);
    DUMP_READ_ONLY_FLAG(trace_frame_rate_override);
    DUMP_READ_ONLY_FLAG(true_hdr_screenshots);
    DUMP_READ_ONLY_FLAG(display_config_error_hal);
@@ -259,7 +258,6 @@ FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_s
FLAG_MANAGER_READ_ONLY_FLAG(override_trusted_overlay, "");
FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, "");
FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, "");
FLAG_MANAGER_READ_ONLY_FLAG(single_hop_screenshot, "");
FLAG_MANAGER_READ_ONLY_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
FLAG_MANAGER_READ_ONLY_FLAG(display_config_error_hal, "");

+0 −1
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ public:
    bool override_trusted_overlay() const;
    bool flush_buffer_slots_to_uncache() const;
    bool force_compile_graphite_renderengine() const;
    bool single_hop_screenshot() const;
    bool trace_frame_rate_override() const;
    bool true_hdr_screenshots() const;
    bool display_config_error_hal() const;
Loading