Set window to transparent when screenshotting layer.
Set the screenshot to transparent instead of black. This allows the
system to draw a color behind without having to crop out the area that
may not be drawn into.
Bug: 76442549
Test: When going to recents, area not drawn from layers is now
transparent instead of black.
Test: Transaction_test#CaptureTransparent
Change-Id: Id535eb753d3d1cae82658cd33423ce588aaa62f8
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e844d11..61ce30c 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -281,7 +281,8 @@
rotation) {}
DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
- : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {}
+ : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
+ mSourceCrop(sourceCrop) {}
const Transform& getTransform() const override { return mDevice->getTransform(); }
Rect getBounds() const override { return mDevice->getBounds(); }
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 6225df1..46ec8e6 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -2,6 +2,15 @@
namespace android {
+float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
+ switch(captureFill) {
+ case CaptureFill::CLEAR:
+ return 0.0f;
+ case CaptureFill::OPAQUE:
+ default:
+ return 1.0f;
+ }
+}
/*
* Checks that the requested width and height are valid and updates them to the render area
* dimensions if they are set to 0
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index bf0707f..62a3d5b 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -9,10 +9,15 @@
namespace android {
class RenderArea {
+
public:
- RenderArea(uint32_t reqHeight, uint32_t reqWidth,
+ enum class CaptureFill {CLEAR, OPAQUE};
+
+ static float getCaptureFillValue(CaptureFill captureFill);
+
+ RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
- : mReqHeight(reqHeight), mReqWidth(reqWidth) {
+ : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
mRotationFlags = Transform::fromRotation(rotation);
}
@@ -36,10 +41,13 @@
status_t updateDimensions();
+ CaptureFill getCaptureFill() const { return mCaptureFill; };
+
private:
uint32_t mReqHeight;
uint32_t mReqWidth;
Transform::orientation_flags mRotationFlags;
+ CaptureFill mCaptureFill;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 183c1eb..781a30c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4597,7 +4597,7 @@
public:
LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
- : RenderArea(reqHeight, reqWidth),
+ : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR),
mLayer(layer),
mCrop(crop),
mFlinger(flinger),
@@ -4834,8 +4834,9 @@
renderArea.getRotationFlags());
engine.disableTexturing();
+ const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
// redraw the screen entirely...
- engine.clearWithColor(0, 0, 0, 1);
+ engine.clearWithColor(0, 0, 0, alpha);
traverseLayers([&](Layer* layer) {
if (filtering) layer->setFiltering(true);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 176c691..a0f12f1 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2358,6 +2358,24 @@
mCapture->expectChildColor(0, 0);
}
+TEST_F(ScreenCaptureTest, CaptureTransparent) {
+ sp<SurfaceControl> child =
+ mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+
+ fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction().show(child).apply(true);
+
+ auto childHandle = child->getHandle();
+
+ // Captures child
+ ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20});
+ mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
+ // Area outside of child's bounds is transparent.
+ mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0});
+}
+
// 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