Loading services/surfaceflinger/SurfaceFlinger.cpp +14 −24 Original line number Diff line number Diff line Loading @@ -7562,6 +7562,12 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, return; } if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } wp<const DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Size reqSize(args.width, args.height); Loading Loading @@ -7692,8 +7698,11 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, std::unordered_set<uint32_t> excludeLayerIds; ui::Dataspace dataspace = args.dataspace; // Call this before holding mStateLock to avoid any deadlocking. bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } { Mutex::Autolock lock(mStateLock); Loading @@ -7705,13 +7714,6 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return; } if (!canCaptureBlackoutContent && parent->getDrawingState().flags & layer_state_t::eLayerSecure) { ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState()); if (args.sourceCrop.width() <= 0) { crop.left = 0; Loading Loading @@ -7889,8 +7891,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); auto future = mScheduler->schedule( [=, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD( kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { Loading @@ -7908,8 +7908,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> renderFuture; renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, canCaptureBlackoutContent, regionSampling, grayscale, captureResults); regionSampling, grayscale, captureResults); }); if (captureListener) { Loading @@ -7936,9 +7935,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); auto layers = getLayerSnapshots(); Loading @@ -7953,14 +7951,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( layerFE->mSnapshot->geomLayerTransform.inverse(); } // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); return ftl::yield<FenceResult>(base::unexpected(PERMISSION_DENIED)).share(); } auto capturedBuffer = buffer; auto requestedDataspace = renderArea->getReqDataSpace(); Loading services/surfaceflinger/SurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -858,8 +858,8 @@ private: bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) REQUIRES(kMainThreadContext); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a Loading services/surfaceflinger/tests/ScreenCapture_test.cpp +31 −14 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) { ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } { UIDFaker f(AID_SYSTEM); // By default the system can capture screenshots with secure layers but they Loading @@ -111,15 +112,31 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) { shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able // to receive them...we are expected to take care with the results. mCaptureArgs.captureSecureLayers = true; // AID_SYSTEM is allowed to capture secure content. ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); ASSERT_TRUE(mCaptureResults.capturedSecureLayers); ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers); sc.expectColor(Rect(0, 0, 32, 32), Color::RED); } { // Attempt secure screenshot from shell since it doesn't have CAPTURE_BLACKOUT_CONTENT // permission, but is allowed normal screenshots. UIDFaker faker(AID_SHELL); ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } // Remove flag secure from the layer. Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); { // Assert that screenshot fails without CAPTURE_BLACKOUT_CONTENT when requesting // captureSecureLayers even if there are no actual secure layers on screen. UIDFaker faker(AID_SHELL); ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } } TEST_F(ScreenCaptureTest, CaptureChildSetParentFlagsSecureEUidSystem) { sp<SurfaceControl> parentLayer; ASSERT_NO_FATAL_FAILURE( Loading services/surfaceflinger/tests/unittests/CompositionTest.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -194,7 +194,6 @@ void CompositionTest::captureScreenComposition() { LayerCase::setupForScreenCapture(this); const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); constexpr bool forSystem = true; constexpr bool regionSampling = false; auto renderArea = DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(), Loading @@ -216,7 +215,7 @@ void CompositionTest::captureScreenComposition() { usage); auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots, mCaptureScreenBuffer, forSystem, regionSampling); mCaptureScreenBuffer, regionSampling); ASSERT_TRUE(future.valid()); const auto fenceResult = future.get(); Loading services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -493,11 +493,11 @@ public: auto renderScreenImpl(std::shared_ptr<const RenderArea> renderArea, SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool forSystem, bool regionSampling) { bool regionSampling) { ScreenCaptureResults captureResults; return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers, buffer, forSystem, regionSampling, buffer, regionSampling, false /* grayscale */, captureResults)); } Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +14 −24 Original line number Diff line number Diff line Loading @@ -7562,6 +7562,12 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, return; } if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } wp<const DisplayDevice> displayWeak; ui::LayerStack layerStack; ui::Size reqSize(args.width, args.height); Loading Loading @@ -7692,8 +7698,11 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, std::unordered_set<uint32_t> excludeLayerIds; ui::Dataspace dataspace = args.dataspace; // Call this before holding mStateLock to avoid any deadlocking. bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } { Mutex::Autolock lock(mStateLock); Loading @@ -7705,13 +7714,6 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return; } if (!canCaptureBlackoutContent && parent->getDrawingState().flags & layer_state_t::eLayerSecure) { ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState()); if (args.sourceCrop.width() <= 0) { crop.left = 0; Loading Loading @@ -7889,8 +7891,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); auto future = mScheduler->schedule( [=, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD( kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { Loading @@ -7908,8 +7908,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> renderFuture; renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, canCaptureBlackoutContent, regionSampling, grayscale, captureResults); regionSampling, grayscale, captureResults); }); if (captureListener) { Loading @@ -7936,9 +7935,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); auto layers = getLayerSnapshots(); Loading @@ -7953,14 +7951,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( layerFE->mSnapshot->geomLayerTransform.inverse(); } // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); return ftl::yield<FenceResult>(base::unexpected(PERMISSION_DENIED)).share(); } auto capturedBuffer = buffer; auto requestedDataspace = renderArea->getReqDataSpace(); Loading
services/surfaceflinger/SurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -858,8 +858,8 @@ private: bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) REQUIRES(kMainThreadContext); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a Loading
services/surfaceflinger/tests/ScreenCapture_test.cpp +31 −14 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) { ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } { UIDFaker f(AID_SYSTEM); // By default the system can capture screenshots with secure layers but they Loading @@ -111,15 +112,31 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) { shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able // to receive them...we are expected to take care with the results. mCaptureArgs.captureSecureLayers = true; // AID_SYSTEM is allowed to capture secure content. ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); ASSERT_TRUE(mCaptureResults.capturedSecureLayers); ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers); sc.expectColor(Rect(0, 0, 32, 32), Color::RED); } { // Attempt secure screenshot from shell since it doesn't have CAPTURE_BLACKOUT_CONTENT // permission, but is allowed normal screenshots. UIDFaker faker(AID_SHELL); ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } // Remove flag secure from the layer. Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); { // Assert that screenshot fails without CAPTURE_BLACKOUT_CONTENT when requesting // captureSecureLayers even if there are no actual secure layers on screen. UIDFaker faker(AID_SHELL); ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults)); } } TEST_F(ScreenCaptureTest, CaptureChildSetParentFlagsSecureEUidSystem) { sp<SurfaceControl> parentLayer; ASSERT_NO_FATAL_FAILURE( Loading
services/surfaceflinger/tests/unittests/CompositionTest.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -194,7 +194,6 @@ void CompositionTest::captureScreenComposition() { LayerCase::setupForScreenCapture(this); const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); constexpr bool forSystem = true; constexpr bool regionSampling = false; auto renderArea = DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(), Loading @@ -216,7 +215,7 @@ void CompositionTest::captureScreenComposition() { usage); auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots, mCaptureScreenBuffer, forSystem, regionSampling); mCaptureScreenBuffer, regionSampling); ASSERT_TRUE(future.valid()); const auto fenceResult = future.get(); Loading
services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +2 −2 Original line number Diff line number Diff line Loading @@ -493,11 +493,11 @@ public: auto renderScreenImpl(std::shared_ptr<const RenderArea> renderArea, SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool forSystem, bool regionSampling) { bool regionSampling) { ScreenCaptureResults captureResults; return FTL_FAKE_GUARD(kMainThreadContext, mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers, buffer, forSystem, regionSampling, buffer, regionSampling, false /* grayscale */, captureResults)); } Loading