Loading services/surfaceflinger/Layer.cpp +64 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <stdint.h> #include <stdlib.h> #include <sys/types.h> #include <algorithm> #include <cutils/compiler.h> #include <cutils/native_handle.h> Loading Loading @@ -1777,27 +1778,79 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, } } /** * Traverse only children in z order, ignoring relative layers. */ void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; LayerVector traverse; for (const wp<Layer>& weakRelative : state.zOrderRelatives) { sp<Layer> strongRelative = weakRelative.promote(); // Only add relative layers that are also descendents of the top most parent of the tree. // If a relative layer is not a descendent, then it should be ignored. if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) { traverse.add(strongRelative); } } for (const sp<Layer>& child : children) { const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a // descendent of the top most parent of the tree. If it's not a descendent, then just add // the child here since it won't be added later as a relative. if (std::binary_search(layersInTree.begin(), layersInTree.end(), childState.zOrderRelativeOf.promote().get())) { continue; } traverse.add(child); } return traverse; } void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree, LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree); size_t i = 0; for (; i < children.size(); i++) { const auto& relative = children[i]; for (; i < list.size(); i++) { const auto& relative = list[i]; if (relative->getZ() >= 0) { break; } relative->traverseChildrenInZOrder(stateSet, visitor); relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } visitor(this); for (; i < children.size(); i++) { const auto& relative = children[i]; relative->traverseChildrenInZOrder(stateSet, visitor); for (; i < list.size(); i++) { const auto& relative = list[i]; relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } } std::vector<Layer*> Layer::getLayersInTree(LayerVector::StateSet stateSet) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; std::vector<Layer*> layersInTree = {this}; for (size_t i = 0; i < children.size(); i++) { const auto& child = children[i]; std::vector<Layer*> childLayers = child->getLayersInTree(stateSet); layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend()); } return layersInTree; } void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { std::vector<Layer*> layersInTree = getLayersInTree(stateSet); std::sort(layersInTree.begin(), layersInTree.end()); traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } Transform Layer::getTransform() const { Loading services/surfaceflinger/Layer.h +21 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ #include "RenderEngine/Texture.h" #include <math/vec4.h> #include <vector> using namespace android::surfaceflinger; Loading Loading @@ -564,6 +565,10 @@ public: const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); /** * Traverse only children in z order, ignoring relative layers that are not children of the * parent. */ void traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); Loading Loading @@ -778,6 +783,22 @@ protected: wp<Layer> mDrawingParent; mutable LayerBE mBE; private: /** * Returns an unsorted vector of all layers that are part of this tree. * That includes the current layer and all its descendants. */ std::vector<Layer*> getLayersInTree(LayerVector::StateSet stateSet); /** * Traverses layers that are part of this tree in the correct z order. * layersInTree must be sorted before calling this method. */ void traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree, LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree); }; // --------------------------------------------------------------------------- Loading services/surfaceflinger/tests/Transaction_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -2376,6 +2376,58 @@ TEST_F(ScreenCaptureTest, CaptureTransparent) { mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); } TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp<SurfaceControl> child = mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); SurfaceComposerClient::Transaction() .show(child) // Set relative layer above fg layer so should be shown above when computing all layers. .setRelativeLayer(relative, fgHandle, 1) .show(relative) .apply(true); // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured. ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp<SurfaceControl> child = mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); SurfaceComposerClient::Transaction() .show(child) // Set relative layer below fg layer but relative to child layer so it should be shown // above child layer. .setLayer(relative, -1) .setRelativeLayer(relative, child->getHandle(), 1) .show(relative) .apply(true); // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its // relative value should be taken into account, placing it above child layer. ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); // Relative layer is showing on top of child layer mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255}); } // In the following tests we verify successful skipping of a parent layer, // so we use the same verification logic and only change how we mutate Loading Loading
services/surfaceflinger/Layer.cpp +64 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <stdint.h> #include <stdlib.h> #include <sys/types.h> #include <algorithm> #include <cutils/compiler.h> #include <cutils/native_handle.h> Loading Loading @@ -1777,27 +1778,79 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, } } /** * Traverse only children in z order, ignoring relative layers. */ void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; LayerVector traverse; for (const wp<Layer>& weakRelative : state.zOrderRelatives) { sp<Layer> strongRelative = weakRelative.promote(); // Only add relative layers that are also descendents of the top most parent of the tree. // If a relative layer is not a descendent, then it should be ignored. if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) { traverse.add(strongRelative); } } for (const sp<Layer>& child : children) { const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a // descendent of the top most parent of the tree. If it's not a descendent, then just add // the child here since it won't be added later as a relative. if (std::binary_search(layersInTree.begin(), layersInTree.end(), childState.zOrderRelativeOf.promote().get())) { continue; } traverse.add(child); } return traverse; } void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree, LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree); size_t i = 0; for (; i < children.size(); i++) { const auto& relative = children[i]; for (; i < list.size(); i++) { const auto& relative = list[i]; if (relative->getZ() >= 0) { break; } relative->traverseChildrenInZOrder(stateSet, visitor); relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } visitor(this); for (; i < children.size(); i++) { const auto& relative = children[i]; relative->traverseChildrenInZOrder(stateSet, visitor); for (; i < list.size(); i++) { const auto& relative = list[i]; relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } } std::vector<Layer*> Layer::getLayersInTree(LayerVector::StateSet stateSet) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; std::vector<Layer*> layersInTree = {this}; for (size_t i = 0; i < children.size(); i++) { const auto& child = children[i]; std::vector<Layer*> childLayers = child->getLayersInTree(stateSet); layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend()); } return layersInTree; } void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { std::vector<Layer*> layersInTree = getLayersInTree(stateSet); std::sort(layersInTree.begin(), layersInTree.end()); traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); } Transform Layer::getTransform() const { Loading
services/surfaceflinger/Layer.h +21 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ #include "RenderEngine/Texture.h" #include <math/vec4.h> #include <vector> using namespace android::surfaceflinger; Loading Loading @@ -564,6 +565,10 @@ public: const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); /** * Traverse only children in z order, ignoring relative layers that are not children of the * parent. */ void traverseChildrenInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); Loading Loading @@ -778,6 +783,22 @@ protected: wp<Layer> mDrawingParent; mutable LayerBE mBE; private: /** * Returns an unsorted vector of all layers that are part of this tree. * That includes the current layer and all its descendants. */ std::vector<Layer*> getLayersInTree(LayerVector::StateSet stateSet); /** * Traverses layers that are part of this tree in the correct z order. * layersInTree must be sorted before calling this method. */ void traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree, LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree); }; // --------------------------------------------------------------------------- Loading
services/surfaceflinger/tests/Transaction_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -2376,6 +2376,58 @@ TEST_F(ScreenCaptureTest, CaptureTransparent) { mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); } TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp<SurfaceControl> child = mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); SurfaceComposerClient::Transaction() .show(child) // Set relative layer above fg layer so should be shown above when computing all layers. .setRelativeLayer(relative, fgHandle, 1) .show(relative) .apply(true); // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured. ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); mCapture->expectChildColor(0, 0); } TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { auto fgHandle = mFGSurfaceControl->getHandle(); sp<SurfaceControl> child = mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); SurfaceComposerClient::Transaction() .show(child) // Set relative layer below fg layer but relative to child layer so it should be shown // above child layer. .setLayer(relative, -1) .setRelativeLayer(relative, child->getHandle(), 1) .show(relative) .apply(true); // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its // relative value should be taken into account, placing it above child layer. ScreenCapture::captureLayers(&mCapture, fgHandle); mCapture->expectFGColor(10, 10); // Relative layer is showing on top of child layer mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255}); } // In the following tests we verify successful skipping of a parent layer, // so we use the same verification logic and only change how we mutate Loading