diff options
-rw-r--r-- | services/surfaceflinger/RegionSamplingThread.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 104 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 6 |
3 files changed, 62 insertions, 52 deletions
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index c888ccc8ae..77e045d6f9 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -377,8 +377,8 @@ void RegionSamplingThread::captureSample() { constexpr bool kIsProtected = false; if (const auto fenceResult = - mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer, - kRegionSampling, kGrayscale, kIsProtected, nullptr) + mFlinger.captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, buffer, + kRegionSampling, kGrayscale, kIsProtected, nullptr) .get(); fenceResult.ok()) { fenceResult.value()->waitForever(LOG_TAG); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index edba50bde6..84956d0cd3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8040,6 +8040,19 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.allowProtected, args.grayscale, captureListener); } +bool SurfaceFlinger::layersHasProtectedLayer( + const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const { + bool protectedLayerFound = false; + for (auto& [_, layerFe] : layers) { + protectedLayerFound |= + (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent); + if (protectedLayerFound) { + break; + } + } + return protectedLayerFound; +} + void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, @@ -8055,6 +8068,9 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, return; } + // Snapshots must be taken from the main thread. + auto layers = mScheduler->schedule([=]() { return getLayerSnapshots(); }).get(); + // Loop over all visible layers to see whether there's any protected layer. A protected layer is // 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 @@ -8062,18 +8078,7 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { - hasProtectedLayer = mScheduler - ->schedule([=]() { - bool protectedLayerFound = false; - auto layers = getLayerSnapshots(); - for (auto& [_, layerFe] : layers) { - protectedLayerFound |= - (layerFe->mSnapshot->isVisible && - layerFe->mSnapshot->hasProtectedContent); - } - return protectedLayerFound; - }) - .get(); + hasProtectedLayer = layersHasProtectedLayer(layers); } const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | @@ -8098,52 +8103,53 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), renderengine::impl::ExternalTexture::Usage:: WRITEABLE); - auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, - false /* regionSampling */, grayscale, isProtected, - captureListener); - fence.get(); + auto futureFence = + captureScreenshot(std::move(renderAreaFuture), getLayerSnapshots, texture, + false /* regionSampling */, grayscale, isProtected, captureListener); + futureFence.get(); } -ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( +ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); - auto future = mScheduler->schedule( - [=, this, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD( - kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { - ScreenCaptureResults captureResults; - std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get(); - 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 takeScreenshotFn = [=, this, renderAreaFuture = std::move(renderAreaFuture)]() REQUIRES( + kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { + ScreenCaptureResults captureResults; + std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get(); + 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(); + } - ftl::SharedFuture<FenceResult> renderFuture; - renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { - renderFuture = - renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, - grayscale, isProtected, captureResults); - }); + ftl::SharedFuture<FenceResult> renderFuture; + renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { + renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, + grayscale, isProtected, captureResults); + }); - 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; - }); + 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; + }; + + 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) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index be057979f9..fdeede1776 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -874,13 +874,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); + bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const; + void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&); - ftl::SharedFuture<FenceResult> captureScreenCommon( + + ftl::SharedFuture<FenceResult> captureScreenshot( RenderAreaFuture, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>&); + ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, |