Loading services/surfaceflinger/LayerRenderArea.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -94,8 +94,22 @@ void LayerRenderArea::render(std::function<void()> drawLayers) { // no need to check rotation because there is none mNeedsFiltering = sourceCrop.width() != getReqWidth() || sourceCrop.height() != getReqHeight(); // If layer is offscreen, update mirroring info if it exists if (mLayer->isRemovedFromCurrentState()) { mLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->updateMirrorInfo(); }); mLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->updateCloneBufferInfo(); }); } if (!mChildrenOnly) { mTransform = mLayer->getTransform().inverse(); // If the layer is offscreen, compute bounds since we don't compute bounds for offscreen // layers in a regular cycles. if (mLayer->isRemovedFromCurrentState()) { FloatRect maxBounds = mFlinger.getMaxDisplayBounds(); mLayer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */); } drawLayers(); } else { uint32_t w = static_cast<uint32_t>(getWidth()); Loading services/surfaceflinger/SurfaceFlinger.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -2455,7 +2455,7 @@ void SurfaceFlinger::postComposition() { } } void SurfaceFlinger::computeLayerBounds() { FloatRect SurfaceFlinger::getMaxDisplayBounds() { // Find the largest width and height among all the displays. int32_t maxDisplayWidth = 0; int32_t maxDisplayHeight = 0; Loading @@ -2473,8 +2473,13 @@ void SurfaceFlinger::computeLayerBounds() { // Ignore display bounds for now since they will be computed later. Use a large Rect bound // to ensure it's bigger than an actual display will be. FloatRect maxBounds(-maxDisplayWidth * 10, -maxDisplayHeight * 10, maxDisplayWidth * 10, maxDisplayHeight * 10); FloatRect maxBounds = FloatRect(-maxDisplayWidth * 10, -maxDisplayHeight * 10, maxDisplayWidth * 10, maxDisplayHeight * 10); return maxBounds; } void SurfaceFlinger::computeLayerBounds() { FloatRect maxBounds = getMaxDisplayBounds(); for (const auto& layer : mDrawingState.layersSortedByZ) { layer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */); } Loading Loading @@ -6167,9 +6172,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, sp<Layer> parent; Rect crop(args.sourceCrop); std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers; Rect layerStackSpaceRect; ui::Dataspace dataspace; bool captureSecureLayers; // Call this before holding mStateLock to avoid any deadlocking. bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); Loading @@ -6178,7 +6181,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, Mutex::Autolock lock(mStateLock); parent = fromHandle(args.layerHandle).promote(); if (parent == nullptr || parent->isRemovedFromCurrentState()) { if (parent == nullptr) { ALOGE("captureLayers called with an invalid or removed parent"); return NAME_NOT_FOUND; } Loading Loading @@ -6217,39 +6220,36 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } } const auto display = findDisplay(WithLayerStack(parent->getLayerStack())); if (!display) { return NAME_NOT_FOUND; } layerStackSpaceRect = display->getLayerStackSpaceRect(); // The dataspace is depended on the color mode of display, that could use non-native mode // (ex. displayP3) to enhance the content, but some cases are checking native RGB in bytes, // and failed if display is not in native mode. This provide a way to force using native // colors when capture. dataspace = args.dataspace; if (dataspace == ui::Dataspace::UNKNOWN) { auto display = findDisplay(WithLayerStack(parent->getLayerStack())); if (!display) { // If the layer is not on a display, use the dataspace for the default display. display = getDefaultDisplayDeviceLocked(); } const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode; dataspace = pickDataspaceFromColorMode(colorMode); } captureSecureLayers = args.captureSecureLayers && display->isSecure(); } // mStateLock // really small crop or frameScale if (reqSize.width <= 0) { reqSize.width = 1; } if (reqSize.height <= 0) { reqSize.height = 1; if (reqSize.width <= 0 || reqSize.height <= 0) { ALOGW("Failed to captureLayes: crop or scale too small"); return BAD_VALUE; } Rect layerStackSpaceRect(0, 0, reqSize.width, reqSize.height); bool childrenOnly = args.childrenOnly; RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> { return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace, childrenOnly, layerStackSpaceRect, captureSecureLayers); args.captureSecureLayers); }); auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) { Loading services/surfaceflinger/SurfaceFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -337,6 +337,7 @@ public: // Disables expensive rendering for all displays // This is scheduled on the main thread void disableExpensiveRendering(); FloatRect getMaxDisplayBounds(); protected: // We're reference counted, never destroy SurfaceFlinger directly Loading services/surfaceflinger/tests/InvalidHandles_test.cpp +0 −11 Original line number Diff line number Diff line Loading @@ -52,17 +52,6 @@ protected: } }; TEST_F(InvalidHandleTest, createSurfaceInvalidParentHandle) { // The createSurface is scheduled now, we could still get a created surface from createSurface. // Should verify if it actually added into current state by checking the screenshot. auto notSc = mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0, mNotSc->getHandle()); LayerCaptureArgs args; args.layerHandle = notSc->getHandle(); ScreenCaptureResults captureResults; ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults)); } TEST_F(InvalidHandleTest, captureLayersInvalidHandle) { LayerCaptureArgs args; args.layerHandle = mNotSc->getHandle(); Loading services/surfaceflinger/tests/MirrorLayer_test.cpp +55 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,61 @@ TEST_F(MirrorLayerTest, InitialMirrorState) { } } // Test that a mirror layer can be screenshot when offscreen TEST_F(MirrorLayerTest, OffscreenMirrorScreenshot) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ui::DisplayMode mode; SurfaceComposerClient::getActiveDisplayMode(display, &mode); const ui::Size& size = mode.resolution; sp<SurfaceControl> grandchild = createLayer("Grandchild layer", 50, 50, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(grandchild, Color::BLUE, 50, 50)); Rect childBounds = Rect(50, 50, 450, 450); asTransaction([&](Transaction& t) { t.setCrop(grandchild, Rect(0, 0, 50, 50)).show(grandchild); t.setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); }); sp<SurfaceControl> mirrorLayer = nullptr; { // Run as system to get the ACCESS_SURFACE_FLINGER permission when mirroring UIDFaker f(AID_SYSTEM); // Mirror mChildLayer mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); ASSERT_NE(mirrorLayer, nullptr); } // Show the mirror layer, but don't reparent to a layer on screen. Transaction().show(mirrorLayer).apply(); { SCOPED_TRACE("Offscreen Mirror"); auto shot = screenshot(); shot->expectColor(Rect(0, 0, size.getWidth(), 50), Color::RED); shot->expectColor(Rect(0, 0, 50, size.getHeight()), Color::RED); shot->expectColor(Rect(450, 0, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(0, 450, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(100, 100, 450, 450), Color::GREEN); shot->expectColor(Rect(50, 50, 100, 100), Color::BLUE); } { SCOPED_TRACE("Capture Mirror"); // Capture just the mirror layer and child. LayerCaptureArgs captureArgs; captureArgs.layerHandle = mirrorLayer->getHandle(); captureArgs.sourceCrop = childBounds; std::unique_ptr<ScreenCapture> shot; ScreenCapture::captureLayers(&shot, captureArgs); shot->expectSize(childBounds.width(), childBounds.height()); shot->expectColor(Rect(0, 0, 50, 50), Color::BLUE); shot->expectColor(Rect(50, 50, 400, 400), Color::GREEN); } } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading Loading
services/surfaceflinger/LayerRenderArea.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -94,8 +94,22 @@ void LayerRenderArea::render(std::function<void()> drawLayers) { // no need to check rotation because there is none mNeedsFiltering = sourceCrop.width() != getReqWidth() || sourceCrop.height() != getReqHeight(); // If layer is offscreen, update mirroring info if it exists if (mLayer->isRemovedFromCurrentState()) { mLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->updateMirrorInfo(); }); mLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->updateCloneBufferInfo(); }); } if (!mChildrenOnly) { mTransform = mLayer->getTransform().inverse(); // If the layer is offscreen, compute bounds since we don't compute bounds for offscreen // layers in a regular cycles. if (mLayer->isRemovedFromCurrentState()) { FloatRect maxBounds = mFlinger.getMaxDisplayBounds(); mLayer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */); } drawLayers(); } else { uint32_t w = static_cast<uint32_t>(getWidth()); Loading
services/surfaceflinger/SurfaceFlinger.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -2455,7 +2455,7 @@ void SurfaceFlinger::postComposition() { } } void SurfaceFlinger::computeLayerBounds() { FloatRect SurfaceFlinger::getMaxDisplayBounds() { // Find the largest width and height among all the displays. int32_t maxDisplayWidth = 0; int32_t maxDisplayHeight = 0; Loading @@ -2473,8 +2473,13 @@ void SurfaceFlinger::computeLayerBounds() { // Ignore display bounds for now since they will be computed later. Use a large Rect bound // to ensure it's bigger than an actual display will be. FloatRect maxBounds(-maxDisplayWidth * 10, -maxDisplayHeight * 10, maxDisplayWidth * 10, maxDisplayHeight * 10); FloatRect maxBounds = FloatRect(-maxDisplayWidth * 10, -maxDisplayHeight * 10, maxDisplayWidth * 10, maxDisplayHeight * 10); return maxBounds; } void SurfaceFlinger::computeLayerBounds() { FloatRect maxBounds = getMaxDisplayBounds(); for (const auto& layer : mDrawingState.layersSortedByZ) { layer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */); } Loading Loading @@ -6167,9 +6172,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, sp<Layer> parent; Rect crop(args.sourceCrop); std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers; Rect layerStackSpaceRect; ui::Dataspace dataspace; bool captureSecureLayers; // Call this before holding mStateLock to avoid any deadlocking. bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); Loading @@ -6178,7 +6181,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, Mutex::Autolock lock(mStateLock); parent = fromHandle(args.layerHandle).promote(); if (parent == nullptr || parent->isRemovedFromCurrentState()) { if (parent == nullptr) { ALOGE("captureLayers called with an invalid or removed parent"); return NAME_NOT_FOUND; } Loading Loading @@ -6217,39 +6220,36 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } } const auto display = findDisplay(WithLayerStack(parent->getLayerStack())); if (!display) { return NAME_NOT_FOUND; } layerStackSpaceRect = display->getLayerStackSpaceRect(); // The dataspace is depended on the color mode of display, that could use non-native mode // (ex. displayP3) to enhance the content, but some cases are checking native RGB in bytes, // and failed if display is not in native mode. This provide a way to force using native // colors when capture. dataspace = args.dataspace; if (dataspace == ui::Dataspace::UNKNOWN) { auto display = findDisplay(WithLayerStack(parent->getLayerStack())); if (!display) { // If the layer is not on a display, use the dataspace for the default display. display = getDefaultDisplayDeviceLocked(); } const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode; dataspace = pickDataspaceFromColorMode(colorMode); } captureSecureLayers = args.captureSecureLayers && display->isSecure(); } // mStateLock // really small crop or frameScale if (reqSize.width <= 0) { reqSize.width = 1; } if (reqSize.height <= 0) { reqSize.height = 1; if (reqSize.width <= 0 || reqSize.height <= 0) { ALOGW("Failed to captureLayes: crop or scale too small"); return BAD_VALUE; } Rect layerStackSpaceRect(0, 0, reqSize.width, reqSize.height); bool childrenOnly = args.childrenOnly; RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> { return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace, childrenOnly, layerStackSpaceRect, captureSecureLayers); args.captureSecureLayers); }); auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) { Loading
services/surfaceflinger/SurfaceFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -337,6 +337,7 @@ public: // Disables expensive rendering for all displays // This is scheduled on the main thread void disableExpensiveRendering(); FloatRect getMaxDisplayBounds(); protected: // We're reference counted, never destroy SurfaceFlinger directly Loading
services/surfaceflinger/tests/InvalidHandles_test.cpp +0 −11 Original line number Diff line number Diff line Loading @@ -52,17 +52,6 @@ protected: } }; TEST_F(InvalidHandleTest, createSurfaceInvalidParentHandle) { // The createSurface is scheduled now, we could still get a created surface from createSurface. // Should verify if it actually added into current state by checking the screenshot. auto notSc = mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0, mNotSc->getHandle()); LayerCaptureArgs args; args.layerHandle = notSc->getHandle(); ScreenCaptureResults captureResults; ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults)); } TEST_F(InvalidHandleTest, captureLayersInvalidHandle) { LayerCaptureArgs args; args.layerHandle = mNotSc->getHandle(); Loading
services/surfaceflinger/tests/MirrorLayer_test.cpp +55 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,61 @@ TEST_F(MirrorLayerTest, InitialMirrorState) { } } // Test that a mirror layer can be screenshot when offscreen TEST_F(MirrorLayerTest, OffscreenMirrorScreenshot) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ui::DisplayMode mode; SurfaceComposerClient::getActiveDisplayMode(display, &mode); const ui::Size& size = mode.resolution; sp<SurfaceControl> grandchild = createLayer("Grandchild layer", 50, 50, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(grandchild, Color::BLUE, 50, 50)); Rect childBounds = Rect(50, 50, 450, 450); asTransaction([&](Transaction& t) { t.setCrop(grandchild, Rect(0, 0, 50, 50)).show(grandchild); t.setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); }); sp<SurfaceControl> mirrorLayer = nullptr; { // Run as system to get the ACCESS_SURFACE_FLINGER permission when mirroring UIDFaker f(AID_SYSTEM); // Mirror mChildLayer mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); ASSERT_NE(mirrorLayer, nullptr); } // Show the mirror layer, but don't reparent to a layer on screen. Transaction().show(mirrorLayer).apply(); { SCOPED_TRACE("Offscreen Mirror"); auto shot = screenshot(); shot->expectColor(Rect(0, 0, size.getWidth(), 50), Color::RED); shot->expectColor(Rect(0, 0, 50, size.getHeight()), Color::RED); shot->expectColor(Rect(450, 0, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(0, 450, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(100, 100, 450, 450), Color::GREEN); shot->expectColor(Rect(50, 50, 100, 100), Color::BLUE); } { SCOPED_TRACE("Capture Mirror"); // Capture just the mirror layer and child. LayerCaptureArgs captureArgs; captureArgs.layerHandle = mirrorLayer->getHandle(); captureArgs.sourceCrop = childBounds; std::unique_ptr<ScreenCapture> shot; ScreenCapture::captureLayers(&shot, captureArgs); shot->expectSize(childBounds.width(), childBounds.height()); shot->expectColor(Rect(0, 0, 50, 50), Color::BLUE); shot->expectColor(Rect(50, 50, 400, 400), Color::GREEN); } } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading