Loading services/surfaceflinger/SurfaceFlinger.cpp +15 −8 Original line number Diff line number Diff line Loading @@ -7838,17 +7838,19 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { ALOGD("Permission denied to captureDisplay"); invokeScreenCaptureError(validate, captureListener); return; } if (!args.displayToken) { ALOGD("Invalid display token to captureDisplay"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Loading @@ -7861,6 +7863,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, Mutex::Autolock lock(mStateLock); sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken); if (!display) { ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -7877,7 +7880,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureDisplay"); ALOGD("Invalid layer handle passed as excludeLayer to captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading Loading @@ -7915,6 +7918,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args const auto display = getDisplayDeviceLocked(displayId); if (!display) { ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -7932,7 +7936,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args constexpr auto kMaxTextureSize = 16384; if (size.width <= 0 || size.height <= 0 || size.width >= kMaxTextureSize || size.height >= kMaxTextureSize) { ALOGE("capture display resolved to invalid size %d x %d", size.width, size.height); ALOGD("captureDisplay resolved to invalid size %d x %d", size.width, size.height); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -7979,6 +7983,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { ALOGD("Permission denied to captureLayers"); invokeScreenCaptureError(validate, captureListener); return; } Loading @@ -7990,7 +7995,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Dataspace dataspace = args.dataspace; if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Loading @@ -8000,7 +8005,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, parent = LayerHandle::getLayer(args.layerHandle); if (parent == nullptr) { ALOGE("captureLayers called with an invalid or removed parent"); ALOGD("captureLayers called with an invalid or removed parent"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -8019,6 +8024,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) { // Error out if the layer has no source bounds (i.e. they are boundless) and a source // crop was not specified, or an invalid frame scale was provided. ALOGD("Boundless layer, unspecified crop, or invalid frame scale to captureLayers"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading @@ -8029,7 +8035,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureLayers"); ALOGD("Invalid layer handle passed as excludeLayer to captureLayers"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -8038,7 +8044,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, // really small crop or frameScale if (reqSize.width <= 0 || reqSize.height <= 0) { ALOGW("Failed to captureLayers: crop or scale too small"); ALOGD("Failed to captureLayers: crop or scale too small"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -8103,7 +8109,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); ALOGD("capture screen must provide a capture listener callback"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -9869,6 +9875,7 @@ binder::Status SurfaceComposerAIDL::captureDisplayById( std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId)); mFlinger->captureDisplay(*id, args, captureListener); } else { ALOGD("Permission denied to captureDisplayById"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); } return binderStatusFromStatusT(NO_ERROR); Loading services/surfaceflinger/tests/LayerTransactionTest.h +4 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,10 @@ protected: return colorLayer; } sp<SurfaceControl> mirrorSurface(SurfaceControl* mirrorFromSurface) { return mClient->mirrorSurface(mirrorFromSurface); } ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); Loading services/surfaceflinger/tests/ScreenCapture_test.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -1039,6 +1039,29 @@ TEST_F(ScreenCaptureTest, CaptureHdrLayer) { ASSERT_TRUE(mCapture->capturedHdrLayers()); } TEST_F(ScreenCaptureTest, captureOffscreenNullSnapshot) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState, mBGSurfaceControl.get())); // A mirrored layer will not have a snapshot. Testing an offscreen mirrored layer // ensures that the screenshot path handles cases where snapshots are null. sp<SurfaceControl> mirroredLayer; ASSERT_NO_FATAL_FAILURE(mirroredLayer = mirrorSurface(layer.get())); LayerCaptureArgs captureArgs; captureArgs.layerHandle = mirroredLayer->getHandle(); captureArgs.sourceCrop = Rect(0, 0, 1, 1); // Screenshot path should only use the children of the layer hierarchy so // that it will not create a new snapshot. A snapshot would otherwise be // created to pass on the properties of the parent, which is not needed // for the purposes of this test since we explicitly want a null snapshot. captureArgs.childrenOnly = true; ScreenCapture::captureLayers(&mCapture, captureArgs); } // 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 // the parent layer to verify that various properties are ignored. Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +15 −8 Original line number Diff line number Diff line Loading @@ -7838,17 +7838,19 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { ALOGD("Permission denied to captureDisplay"); invokeScreenCaptureError(validate, captureListener); return; } if (!args.displayToken) { ALOGD("Invalid display token to captureDisplay"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Loading @@ -7861,6 +7863,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, Mutex::Autolock lock(mStateLock); sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken); if (!display) { ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -7877,7 +7880,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureDisplay"); ALOGD("Invalid layer handle passed as excludeLayer to captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading Loading @@ -7915,6 +7918,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args const auto display = getDisplayDeviceLocked(displayId); if (!display) { ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -7932,7 +7936,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args constexpr auto kMaxTextureSize = 16384; if (size.width <= 0 || size.height <= 0 || size.width >= kMaxTextureSize || size.height >= kMaxTextureSize) { ALOGE("capture display resolved to invalid size %d x %d", size.width, size.height); ALOGD("captureDisplay resolved to invalid size %d x %d", size.width, size.height); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -7979,6 +7983,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { ALOGD("Permission denied to captureLayers"); invokeScreenCaptureError(validate, captureListener); return; } Loading @@ -7990,7 +7995,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Dataspace dataspace = args.dataspace; if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } Loading @@ -8000,7 +8005,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, parent = LayerHandle::getLayer(args.layerHandle); if (parent == nullptr) { ALOGE("captureLayers called with an invalid or removed parent"); ALOGD("captureLayers called with an invalid or removed parent"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -8019,6 +8024,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) { // Error out if the layer has no source bounds (i.e. they are boundless) and a source // crop was not specified, or an invalid frame scale was provided. ALOGD("Boundless layer, unspecified crop, or invalid frame scale to captureLayers"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading @@ -8029,7 +8035,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureLayers"); ALOGD("Invalid layer handle passed as excludeLayer to captureLayers"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } Loading @@ -8038,7 +8044,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, // really small crop or frameScale if (reqSize.width <= 0 || reqSize.height <= 0) { ALOGW("Failed to captureLayers: crop or scale too small"); ALOGD("Failed to captureLayers: crop or scale too small"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -8103,7 +8109,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); ALOGD("capture screen must provide a capture listener callback"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } Loading Loading @@ -9869,6 +9875,7 @@ binder::Status SurfaceComposerAIDL::captureDisplayById( std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId)); mFlinger->captureDisplay(*id, args, captureListener); } else { ALOGD("Permission denied to captureDisplayById"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); } return binderStatusFromStatusT(NO_ERROR); Loading
services/surfaceflinger/tests/LayerTransactionTest.h +4 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,10 @@ protected: return colorLayer; } sp<SurfaceControl> mirrorSurface(SurfaceControl* mirrorFromSurface) { return mClient->mirrorSurface(mirrorFromSurface); } ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); Loading
services/surfaceflinger/tests/ScreenCapture_test.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -1039,6 +1039,29 @@ TEST_F(ScreenCaptureTest, CaptureHdrLayer) { ASSERT_TRUE(mCapture->capturedHdrLayers()); } TEST_F(ScreenCaptureTest, captureOffscreenNullSnapshot) { sp<SurfaceControl> layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState, mBGSurfaceControl.get())); // A mirrored layer will not have a snapshot. Testing an offscreen mirrored layer // ensures that the screenshot path handles cases where snapshots are null. sp<SurfaceControl> mirroredLayer; ASSERT_NO_FATAL_FAILURE(mirroredLayer = mirrorSurface(layer.get())); LayerCaptureArgs captureArgs; captureArgs.layerHandle = mirroredLayer->getHandle(); captureArgs.sourceCrop = Rect(0, 0, 1, 1); // Screenshot path should only use the children of the layer hierarchy so // that it will not create a new snapshot. A snapshot would otherwise be // created to pass on the properties of the parent, which is not needed // for the purposes of this test since we explicitly want a null snapshot. captureArgs.childrenOnly = true; ScreenCapture::captureLayers(&mCapture, captureArgs); } // 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 // the parent layer to verify that various properties are ignored. Loading