Loading libs/gui/ISurfaceComposer.cpp +35 −55 Original line number Diff line number Diff line Loading @@ -111,59 +111,49 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation, bool captureSecureLayers) { virtual status_t captureDisplay(const DisplayCaptureArgs& args, ScreenCaptureResults& captureResults) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); data.writeInt32(static_cast<int32_t>(reqDataspace)); data.writeInt32(static_cast<int32_t>(reqPixelFormat)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); data.writeInt32(static_cast<int32_t>(captureSecureLayers)); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); status_t result = args.write(data); if (result != NO_ERROR) { ALOGE("captureDisplay failed to parcel args: %d", result); return result; } result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); if (result != NO_ERROR) { ALOGE("captureScreen failed to transact: %d", result); ALOGE("captureDisplay failed to transact: %d", result); return result; } result = reply.readInt32(); if (result != NO_ERROR) { ALOGE("captureScreen failed to readInt32: %d", result); ALOGE("captureDisplay failed to readInt32: %d", result); return result; } *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); outCapturedSecureLayers = reply.readBool(); captureResults.read(reply); return result; } virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) { virtual status_t captureDisplay(uint64_t displayOrLayerStack, ScreenCaptureResults& captureResults) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeUint64(displayOrLayerStack); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_BY_ID, data, &reply); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); if (result != NO_ERROR) { ALOGE("captureScreen failed to transact: %d", result); ALOGE("captureDisplay failed to transact: %d", result); return result; } result = reply.readInt32(); if (result != NO_ERROR) { ALOGE("captureScreen failed to readInt32: %d", result); ALOGE("captureDisplay failed to readInt32: %d", result); return result; } *outDataspace = static_cast<ui::Dataspace>(reply.readInt32()); *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); captureResults.read(reply); return result; } Loading Loading @@ -1293,43 +1283,33 @@ status_t BnSurfaceComposer::onTransact( bootFinished(); return NO_ERROR; } case CAPTURE_SCREEN: { case CAPTURE_DISPLAY: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); ui::Dataspace reqDataspace = static_cast<ui::Dataspace>(data.readInt32()); ui::PixelFormat reqPixelFormat = static_cast<ui::PixelFormat>(data.readInt32()); sp<GraphicBuffer> outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); uint32_t reqHeight = data.readUint32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); int32_t rotation = data.readInt32(); bool captureSecureLayers = static_cast<bool>(data.readInt32()); bool capturedSecureLayers = false; status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, ui::toRotation(rotation), captureSecureLayers); DisplayCaptureArgs args; ScreenCaptureResults captureResults; status_t res = args.read(data); if (res != NO_ERROR) { reply->writeInt32(res); return NO_ERROR; } res = captureDisplay(args, captureResults); reply->writeInt32(res); if (res == NO_ERROR) { reply->write(*outBuffer); reply->writeBool(capturedSecureLayers); captureResults.write(*reply); } return NO_ERROR; } case CAPTURE_SCREEN_BY_ID: { case CAPTURE_DISPLAY_BY_ID: { CHECK_INTERFACE(ISurfaceComposer, data, reply); uint64_t displayOrLayerStack = data.readUint64(); ui::Dataspace outDataspace = ui::Dataspace::V0_SRGB; sp<GraphicBuffer> outBuffer; status_t res = captureScreen(displayOrLayerStack, &outDataspace, &outBuffer); ScreenCaptureResults captureResults; status_t res = captureDisplay(displayOrLayerStack, captureResults); reply->writeInt32(res); if (res == NO_ERROR) { reply->writeInt32(static_cast<int32_t>(outDataspace)); reply->write(*outBuffer); captureResults.write(*reply); } return NO_ERROR; } Loading libs/gui/SurfaceComposerClient.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -1922,19 +1922,31 @@ status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColo // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace, status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace /* reqDataspace */, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation, bool captureSecureLayers, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation, captureSecureLayers); DisplayCaptureArgs args; args.displayToken = display; args.pixelFormat = reqPixelFormat; args.sourceCrop = sourceCrop; args.width = reqWidth; args.height = reqHeight; args.useIdentityTransform = useIdentityTransform; args.rotation = rotation; args.captureSecureLayers = captureSecureLayers; ScreenCaptureResults captureResults; status_t ret = s->captureDisplay(args, captureResults); if (ret != NO_ERROR) { return ret; } *outBuffer = captureResults.buffer; outCapturedSecureLayers = captureResults.capturedSecureLayers; return ret; } Loading @@ -1951,7 +1963,11 @@ status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer); ScreenCaptureResults captureResults; status_t ret = s->captureDisplay(displayOrLayerStack, captureResults); *outBuffer = captureResults.buffer; *outDataspace = captureResults.capturedDataspace; return ret; } status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace, Loading libs/gui/include/gui/ISurfaceComposer.h +11 −56 Original line number Diff line number Diff line Loading @@ -48,11 +48,14 @@ namespace android { struct client_cache_t; struct ComposerState; struct DisplayCaptureArgs; struct DisplayConfig; struct DisplayInfo; struct DisplayStatInfo; struct DisplayState; struct InputWindowCommands; struct LayerCaptureArgs; struct ScreenCaptureResults; class LayerDebugInfo; class HdrCapabilities; class IDisplayEventConnection; Loading Loading @@ -246,65 +249,17 @@ public: /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on * screen. * screen and DisplayCaptureArgs.captureSecureLayers is false. * * This function can capture a subregion (the source crop) of the screen. * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. * * reqDataspace and reqPixelFormat specify the data space and pixel format * of the buffer. The caller should pick the data space and pixel format * that it can consume. * * sourceCrop is the crop on the logical display. * * reqWidth and reqHeight specifies the size of the buffer. When either * of them is 0, they are set to the size of the logical display viewport. * * When useIdentityTransform is true, layer transformations are disabled. * * rotation specifies the rotation of the source crop (and the pixels in * it) around its center. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation = ui::ROTATION_0, bool captureSecureLayers = false) = 0; /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on * screen. * * This function can capture a subregion (the source crop) of the screen * into an sRGB buffer with RGBA_8888 pixel format. * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. * * At the moment, sourceCrop is ignored and is always set to the visible * region (projected display viewport) of the screen. * * reqWidth and reqHeight specifies the size of the buffer. When either * of them is 0, they are set to the size of the logical display viewport. * * When useIdentityTransform is true, layer transformations are disabled. * * rotation specifies the rotation of the source crop (and the pixels in * it) around its center. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation = ui::ROTATION_0) { bool outIgnored; return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation); } */ virtual status_t captureDisplay(const DisplayCaptureArgs& args, ScreenCaptureResults& captureResults) = 0; virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) = 0; virtual status_t captureDisplay(uint64_t displayOrLayerStack, ScreenCaptureResults& captureResults) = 0; template <class AA> struct SpHash { Loading Loading @@ -562,7 +517,7 @@ public: GET_DISPLAY_CONFIGS, GET_ACTIVE_CONFIG, GET_DISPLAY_STATE, CAPTURE_SCREEN, CAPTURE_DISPLAY, CAPTURE_LAYERS, CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, Loading Loading @@ -590,7 +545,7 @@ public: GET_DESIRED_DISPLAY_CONFIG_SPECS, GET_DISPLAY_BRIGHTNESS_SUPPORT, SET_DISPLAY_BRIGHTNESS, CAPTURE_SCREEN_BY_ID, CAPTURE_DISPLAY_BY_ID, NOTIFY_POWER_BOOST, SET_GLOBAL_SHADOW_SETTINGS, GET_AUTO_LOW_LATENCY_MODE_SUPPORT, Loading libs/gui/tests/BLASTBufferQueue_test.cpp +19 −31 Original line number Diff line number Diff line Loading @@ -120,6 +120,8 @@ protected: .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); mCaptureArgs.displayToken = mDisplayToken; } void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) { Loading Loading @@ -165,13 +167,14 @@ protected: void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0, bool outsideRegion = false) { sp<GraphicBuffer>& captureBuf = mCaptureResults.buffer; const auto epsilon = 3; const auto width = mScreenCaptureBuf->getWidth(); const auto height = mScreenCaptureBuf->getHeight(); const auto stride = mScreenCaptureBuf->getStride(); const auto width = captureBuf->getWidth(); const auto height = captureBuf->getHeight(); const auto stride = captureBuf->getStride(); uint32_t* bufData; mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN), captureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN), reinterpret_cast<void**>(&bufData)); for (uint32_t row = 0; row < height; row++) { Loading @@ -196,7 +199,7 @@ protected: } } } mScreenCaptureBuf->unlock(); captureBuf->unlock(); ASSERT_EQ(false, ::testing::Test::HasFailure()); } Loading @@ -206,10 +209,12 @@ protected: sp<IBinder> mDisplayToken; sp<SurfaceControl> mSurfaceControl; sp<GraphicBuffer> mScreenCaptureBuf; uint32_t mDisplayWidth; uint32_t mDisplayHeight; DisplayCaptureArgs mCaptureArgs; ScreenCaptureResults mCaptureResults; }; TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) { Loading Loading @@ -301,12 +306,7 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } Loading Loading @@ -383,12 +383,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } Loading Loading @@ -444,12 +440,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); Loading Loading @@ -489,12 +481,8 @@ public: ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); switch (tr) { case ui::Transform::ROT_0: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, Loading libs/gui/tests/Surface_test.cpp +12 −16 Original line number Diff line number Diff line Loading @@ -244,11 +244,13 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) { const sp<IBinder> display = sf->getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); sp<GraphicBuffer> outBuffer; bool ignored; ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); DisplayCaptureArgs captureArgs; captureArgs.displayToken = display; captureArgs.width = 64; captureArgs.height = 64; ScreenCaptureResults captureResults; ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU)); Loading Loading @@ -278,9 +280,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults)); } TEST_F(SurfaceTest, ConcreteTypeIsSurface) { Loading Loading @@ -742,12 +742,8 @@ public: } status_t setActiveColorMode(const sp<IBinder>& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp<IBinder>& /*display*/, sp<GraphicBuffer>* /*outBuffer*/, bool& /*outCapturedSecureLayers*/, ui::Dataspace /*reqDataspace*/, ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, bool /*useIdentityTransform*/, ui::Rotation, bool /*captureSecureLayers*/) override { status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */, ScreenCaptureResults& /* captureResults */) override { return NO_ERROR; } status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/, Loading @@ -760,8 +756,8 @@ public: return NO_ERROR; } void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/, sp<GraphicBuffer>* /*outBuffer*/) override { status_t captureDisplay(uint64_t /*displayOrLayerStack*/, ScreenCaptureResults& /* captureResults */) override { return NO_ERROR; } virtual status_t captureLayers( Loading Loading
libs/gui/ISurfaceComposer.cpp +35 −55 Original line number Diff line number Diff line Loading @@ -111,59 +111,49 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation, bool captureSecureLayers) { virtual status_t captureDisplay(const DisplayCaptureArgs& args, ScreenCaptureResults& captureResults) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); data.writeInt32(static_cast<int32_t>(reqDataspace)); data.writeInt32(static_cast<int32_t>(reqPixelFormat)); data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); data.writeInt32(static_cast<int32_t>(captureSecureLayers)); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); status_t result = args.write(data); if (result != NO_ERROR) { ALOGE("captureDisplay failed to parcel args: %d", result); return result; } result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); if (result != NO_ERROR) { ALOGE("captureScreen failed to transact: %d", result); ALOGE("captureDisplay failed to transact: %d", result); return result; } result = reply.readInt32(); if (result != NO_ERROR) { ALOGE("captureScreen failed to readInt32: %d", result); ALOGE("captureDisplay failed to readInt32: %d", result); return result; } *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); outCapturedSecureLayers = reply.readBool(); captureResults.read(reply); return result; } virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) { virtual status_t captureDisplay(uint64_t displayOrLayerStack, ScreenCaptureResults& captureResults) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeUint64(displayOrLayerStack); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_BY_ID, data, &reply); status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); if (result != NO_ERROR) { ALOGE("captureScreen failed to transact: %d", result); ALOGE("captureDisplay failed to transact: %d", result); return result; } result = reply.readInt32(); if (result != NO_ERROR) { ALOGE("captureScreen failed to readInt32: %d", result); ALOGE("captureDisplay failed to readInt32: %d", result); return result; } *outDataspace = static_cast<ui::Dataspace>(reply.readInt32()); *outBuffer = new GraphicBuffer(); reply.read(**outBuffer); captureResults.read(reply); return result; } Loading Loading @@ -1293,43 +1283,33 @@ status_t BnSurfaceComposer::onTransact( bootFinished(); return NO_ERROR; } case CAPTURE_SCREEN: { case CAPTURE_DISPLAY: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); ui::Dataspace reqDataspace = static_cast<ui::Dataspace>(data.readInt32()); ui::PixelFormat reqPixelFormat = static_cast<ui::PixelFormat>(data.readInt32()); sp<GraphicBuffer> outBuffer; Rect sourceCrop(Rect::EMPTY_RECT); data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); uint32_t reqHeight = data.readUint32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); int32_t rotation = data.readInt32(); bool captureSecureLayers = static_cast<bool>(data.readInt32()); bool capturedSecureLayers = false; status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, ui::toRotation(rotation), captureSecureLayers); DisplayCaptureArgs args; ScreenCaptureResults captureResults; status_t res = args.read(data); if (res != NO_ERROR) { reply->writeInt32(res); return NO_ERROR; } res = captureDisplay(args, captureResults); reply->writeInt32(res); if (res == NO_ERROR) { reply->write(*outBuffer); reply->writeBool(capturedSecureLayers); captureResults.write(*reply); } return NO_ERROR; } case CAPTURE_SCREEN_BY_ID: { case CAPTURE_DISPLAY_BY_ID: { CHECK_INTERFACE(ISurfaceComposer, data, reply); uint64_t displayOrLayerStack = data.readUint64(); ui::Dataspace outDataspace = ui::Dataspace::V0_SRGB; sp<GraphicBuffer> outBuffer; status_t res = captureScreen(displayOrLayerStack, &outDataspace, &outBuffer); ScreenCaptureResults captureResults; status_t res = captureDisplay(displayOrLayerStack, captureResults); reply->writeInt32(res); if (res == NO_ERROR) { reply->writeInt32(static_cast<int32_t>(outDataspace)); reply->write(*outBuffer); captureResults.write(*reply); } return NO_ERROR; } Loading
libs/gui/SurfaceComposerClient.cpp +21 −5 Original line number Diff line number Diff line Loading @@ -1922,19 +1922,31 @@ status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColo // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace reqDataSpace, status_t ScreenshotClient::capture(const sp<IBinder>& display, ui::Dataspace /* reqDataspace */, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation, bool captureSecureLayers, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation, captureSecureLayers); DisplayCaptureArgs args; args.displayToken = display; args.pixelFormat = reqPixelFormat; args.sourceCrop = sourceCrop; args.width = reqWidth; args.height = reqHeight; args.useIdentityTransform = useIdentityTransform; args.rotation = rotation; args.captureSecureLayers = captureSecureLayers; ScreenCaptureResults captureResults; status_t ret = s->captureDisplay(args, captureResults); if (ret != NO_ERROR) { return ret; } *outBuffer = captureResults.buffer; outCapturedSecureLayers = captureResults.capturedSecureLayers; return ret; } Loading @@ -1951,7 +1963,11 @@ status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer); ScreenCaptureResults captureResults; status_t ret = s->captureDisplay(displayOrLayerStack, captureResults); *outBuffer = captureResults.buffer; *outDataspace = captureResults.capturedDataspace; return ret; } status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, ui::Dataspace reqDataSpace, Loading
libs/gui/include/gui/ISurfaceComposer.h +11 −56 Original line number Diff line number Diff line Loading @@ -48,11 +48,14 @@ namespace android { struct client_cache_t; struct ComposerState; struct DisplayCaptureArgs; struct DisplayConfig; struct DisplayInfo; struct DisplayStatInfo; struct DisplayState; struct InputWindowCommands; struct LayerCaptureArgs; struct ScreenCaptureResults; class LayerDebugInfo; class HdrCapabilities; class IDisplayEventConnection; Loading Loading @@ -246,65 +249,17 @@ public: /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on * screen. * screen and DisplayCaptureArgs.captureSecureLayers is false. * * This function can capture a subregion (the source crop) of the screen. * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. * * reqDataspace and reqPixelFormat specify the data space and pixel format * of the buffer. The caller should pick the data space and pixel format * that it can consume. * * sourceCrop is the crop on the logical display. * * reqWidth and reqHeight specifies the size of the buffer. When either * of them is 0, they are set to the size of the logical display viewport. * * When useIdentityTransform is true, layer transformations are disabled. * * rotation specifies the rotation of the source crop (and the pixels in * it) around its center. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation = ui::ROTATION_0, bool captureSecureLayers = false) = 0; /** * Capture the specified screen. This requires READ_FRAME_BUFFER * permission. This function will fail if there is a secure window on * screen. * * This function can capture a subregion (the source crop) of the screen * into an sRGB buffer with RGBA_8888 pixel format. * The subregion can be optionally rotated. It will also be scaled to * match the size of the output buffer. * * At the moment, sourceCrop is ignored and is always set to the visible * region (projected display viewport) of the screen. * * reqWidth and reqHeight specifies the size of the buffer. When either * of them is 0, they are set to the size of the logical display viewport. * * When useIdentityTransform is true, layer transformations are disabled. * * rotation specifies the rotation of the source crop (and the pixels in * it) around its center. */ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, ui::Rotation rotation = ui::ROTATION_0) { bool outIgnored; return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation); } */ virtual status_t captureDisplay(const DisplayCaptureArgs& args, ScreenCaptureResults& captureResults) = 0; virtual status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp<GraphicBuffer>* outBuffer) = 0; virtual status_t captureDisplay(uint64_t displayOrLayerStack, ScreenCaptureResults& captureResults) = 0; template <class AA> struct SpHash { Loading Loading @@ -562,7 +517,7 @@ public: GET_DISPLAY_CONFIGS, GET_ACTIVE_CONFIG, GET_DISPLAY_STATE, CAPTURE_SCREEN, CAPTURE_DISPLAY, CAPTURE_LAYERS, CLEAR_ANIMATION_FRAME_STATS, GET_ANIMATION_FRAME_STATS, Loading Loading @@ -590,7 +545,7 @@ public: GET_DESIRED_DISPLAY_CONFIG_SPECS, GET_DISPLAY_BRIGHTNESS_SUPPORT, SET_DISPLAY_BRIGHTNESS, CAPTURE_SCREEN_BY_ID, CAPTURE_DISPLAY_BY_ID, NOTIFY_POWER_BOOST, SET_GLOBAL_SHADOW_SETTINGS, GET_AUTO_LOW_LATENCY_MODE_SUPPORT, Loading
libs/gui/tests/BLASTBufferQueue_test.cpp +19 −31 Original line number Diff line number Diff line Loading @@ -120,6 +120,8 @@ protected: .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); mCaptureArgs.displayToken = mDisplayToken; } void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) { Loading Loading @@ -165,13 +167,14 @@ protected: void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b, Rect region, int32_t border = 0, bool outsideRegion = false) { sp<GraphicBuffer>& captureBuf = mCaptureResults.buffer; const auto epsilon = 3; const auto width = mScreenCaptureBuf->getWidth(); const auto height = mScreenCaptureBuf->getHeight(); const auto stride = mScreenCaptureBuf->getStride(); const auto width = captureBuf->getWidth(); const auto height = captureBuf->getHeight(); const auto stride = captureBuf->getStride(); uint32_t* bufData; mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN), captureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN), reinterpret_cast<void**>(&bufData)); for (uint32_t row = 0; row < height; row++) { Loading @@ -196,7 +199,7 @@ protected: } } } mScreenCaptureBuf->unlock(); captureBuf->unlock(); ASSERT_EQ(false, ::testing::Test::HasFailure()); } Loading @@ -206,10 +209,12 @@ protected: sp<IBinder> mDisplayToken; sp<SurfaceControl> mSurfaceControl; sp<GraphicBuffer> mScreenCaptureBuf; uint32_t mDisplayWidth; uint32_t mDisplayHeight; DisplayCaptureArgs mCaptureArgs; ScreenCaptureResults mCaptureResults; }; TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) { Loading Loading @@ -301,12 +306,7 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } Loading Loading @@ -383,12 +383,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } Loading Loading @@ -444,12 +440,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { adapter.waitForCallbacks(); // capture screen and verify that it is red bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( checkScreenCapture(r, g, b, {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); Loading Loading @@ -489,12 +481,8 @@ public: ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; ASSERT_EQ(NO_ERROR, mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), mDisplayWidth, mDisplayHeight, /*useIdentityTransform*/ false)); ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults)); switch (tr) { case ui::Transform::ROT_0: ASSERT_NO_FATAL_FAILURE(checkScreenCapture(0, 0, 0, Loading
libs/gui/tests/Surface_test.cpp +12 −16 Original line number Diff line number Diff line Loading @@ -244,11 +244,13 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) { const sp<IBinder> display = sf->getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); sp<GraphicBuffer> outBuffer; bool ignored; ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); DisplayCaptureArgs captureArgs; captureArgs.displayToken = display; captureArgs.width = 64; captureArgs.height = 64; ScreenCaptureResults captureResults; ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults)); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU)); Loading Loading @@ -278,9 +280,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersDontSucceed) { &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, ignored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 64, 64, false)); ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults)); } TEST_F(SurfaceTest, ConcreteTypeIsSurface) { Loading Loading @@ -742,12 +742,8 @@ public: } status_t setActiveColorMode(const sp<IBinder>& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp<IBinder>& /*display*/, sp<GraphicBuffer>* /*outBuffer*/, bool& /*outCapturedSecureLayers*/, ui::Dataspace /*reqDataspace*/, ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, bool /*useIdentityTransform*/, ui::Rotation, bool /*captureSecureLayers*/) override { status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */, ScreenCaptureResults& /* captureResults */) override { return NO_ERROR; } status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/, Loading @@ -760,8 +756,8 @@ public: return NO_ERROR; } void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {} status_t captureScreen(uint64_t /*displayOrLayerStack*/, ui::Dataspace* /*outDataspace*/, sp<GraphicBuffer>* /*outBuffer*/) override { status_t captureDisplay(uint64_t /*displayOrLayerStack*/, ScreenCaptureResults& /* captureResults */) override { return NO_ERROR; } virtual status_t captureLayers( Loading