SurfaceFlinger: Add exclusion list for captureLayers.
Among other use cases, WM needs to be able to omit the IME from Task Snapshots,
even while it is on-screen.
Bug: 126614127
Test: Transaction_test.cpp#CaptureLayerExclude,CaptureLayerExcludeTree
Change-Id: I055d99106c9ce2ed90d64eca06961d88cbd5e2d4
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5676c59..fccd910 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5405,10 +5405,11 @@
useIdentityTransform);
}
-status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
- sp<GraphicBuffer>* outBuffer, const Dataspace reqDataspace,
- const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
- float frameScale, bool childrenOnly) {
+status_t SurfaceFlinger::captureLayers(
+ const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer,
+ const Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
+ const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& excludeHandles,
+ float frameScale, bool childrenOnly) {
ATRACE_CALL();
class LayerRenderArea : public RenderArea {
@@ -5530,15 +5531,36 @@
reqHeight = 1;
}
- LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
+ std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
+ for (const auto& handle : excludeHandles) {
+ BBinder* local = handle->localBinder();
+ if (local != nullptr) {
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(local);
+ excludeLayers.emplace(layerHandle->owner.promote());
+ } else {
+ ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
+ return NAME_NOT_FOUND;
+ }
+ }
- auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
+ LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, reqDataspace, childrenOnly);
+ auto traverseLayers = [parent, childrenOnly,
+ &excludeLayers](const LayerVector::Visitor& visitor) {
parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
if (!layer->isVisible()) {
return;
} else if (childrenOnly && layer == parent.get()) {
return;
}
+
+ sp<Layer> p = layer;
+ while (p != nullptr) {
+ if (excludeLayers.count(p) != 0) {
+ return;
+ }
+ p = p->getParent();
+ }
+
visitor(layer);
});
};