summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
author Chavi Weingarten <chaviw@google.com> 2019-05-09 17:21:57 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-05-09 17:21:57 +0000
commitafab4f0519c8344bb44d0e31ce1a3847c53a0c90 (patch)
tree4e6b51f7cc6974277b93247caaf5c86dbf9c65da /services/surfaceflinger/SurfaceFlinger.cpp
parent7c28c970f3c3b0bea96c7daee269771c94c63d36 (diff)
parent93df2ea991d6f9c5c64280ac9947e44653d61fbf (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.cpp68
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,