diff options
| author | 2019-05-09 17:21:57 +0000 | |
|---|---|---|
| committer | 2019-05-09 17:21:57 +0000 | |
| commit | afab4f0519c8344bb44d0e31ce1a3847c53a0c90 (patch) | |
| tree | 4e6b51f7cc6974277b93247caaf5c86dbf9c65da /services/surfaceflinger/SurfaceFlinger.cpp | |
| parent | 7c28c970f3c3b0bea96c7daee269771c94c63d36 (diff) | |
| parent | 93df2ea991d6f9c5c64280ac9947e44653d61fbf (diff) | |
Merge "Added captureScreen function for displayId or layerStack" into qt-dev
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f8745f7ac3..8f7420fe2d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5089,6 +5089,14 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { ALOGE("Attempting to access SurfaceFlinger with unused code: %u", code); return PERMISSION_DENIED; } + case CAPTURE_SCREEN_BY_ID: { + IPCThreadState* ipc = IPCThreadState::self(); + const int uid = ipc->getCallingUid(); + if ((uid == AID_GRAPHICS) || (uid == AID_SYSTEM) || (uid == AID_SHELL)) { + return OK; + } + return PERMISSION_DENIED; + } } // These codes are used for the IBinder protocol to either interrogate the recipient @@ -5503,6 +5511,66 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken, useIdentityTransform, outCapturedSecureLayers); } +static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) { + switch (colorMode) { + case ColorMode::DISPLAY_P3: + case ColorMode::BT2100_PQ: + case ColorMode::BT2100_HLG: + case ColorMode::DISPLAY_BT2020: + return Dataspace::DISPLAY_P3; + default: + return Dataspace::V0_SRGB; + } +} + +const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) { + const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack}); + if (displayToken) { + return getDisplayDeviceLocked(displayToken); + } + // Couldn't find display by displayId. Try to get display by layerStack since virtual displays + // may not have a displayId. + for (const auto& [token, display] : mDisplays) { + if (display->getLayerStack() == displayOrLayerStack) { + return display; + } + } + return nullptr; +} + +status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* outDataspace, + sp<GraphicBuffer>* outBuffer) { + sp<DisplayDevice> display; + uint32_t width; + uint32_t height; + ui::Transform::orientation_flags captureOrientation; + { + Mutex::Autolock _l(mStateLock); + display = getDisplayByIdOrLayerStack(displayOrLayerStack); + if (!display) { + return BAD_VALUE; + } + + width = uint32_t(display->getViewport().width()); + height = uint32_t(display->getViewport().height()); + + captureOrientation = fromSurfaceComposerRotation( + static_cast<ISurfaceComposer::Rotation>(display->getOrientation())); + *outDataspace = + pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode); + } + + DisplayRenderArea renderArea(display, Rect(), width, height, *outDataspace, captureOrientation, + false /* captureSecureLayers */); + + auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display, + std::placeholders::_1); + bool ignored = false; + return captureScreenCommon(renderArea, traverseLayers, outBuffer, ui::PixelFormat::RGBA_8888, + false /* useIdentityTransform */, + ignored /* outCapturedSecureLayers */); +} + status_t SurfaceFlinger::captureLayers( const sp<IBinder>& layerHandleBinder, sp<GraphicBuffer>* outBuffer, const Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, |