Allow offscreen mirrored layers to be captured.
If an offscreen layer is valid and has content, we should be able to
take a screen capture of it.
If we're mirroring content, but it's not on screen, we need
to ensure updateMirrorInfo is called to get the updated hierarchy. This
will allow the mirror content to get properly screenshot
Test: screencapture offscreen
Test: MirrorLayerTest
Test: ScreenCaptureTest
Change-Id: I31f806eb616e2d6f800da6328c9878a3e47d6a14
Bug: 188222480
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8d7221c..d4e28ce 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2428,7 +2428,7 @@
}
}
-void SurfaceFlinger::computeLayerBounds() {
+FloatRect SurfaceFlinger::getMaxDisplayBounds() {
// Find the largest width and height among all the displays.
int32_t maxDisplayWidth = 0;
int32_t maxDisplayHeight = 0;
@@ -2446,8 +2446,13 @@
// 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 */);
}
@@ -5978,9 +5983,7 @@
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();
@@ -5989,7 +5992,7 @@
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;
}
@@ -6028,43 +6031,38 @@
}
}
- const auto display =
- findDisplay([layerStack = parent->getLayerStack()](const auto& display) {
- return display.getLayerStack() == layerStack;
- });
-
- 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([layerStack = parent->getLayerStack()](const auto& display) {
+ return display.getLayerStack() == layerStack;
+ });
+ 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) {