summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeimy Santiago Morales <jeimysantiago@google.com> 2023-08-04 20:10:58 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-08-04 20:10:58 +0000
commit10d3ca60da03d21dd52d0635319147f334ab2b37 (patch)
treed96bf01da32f0fb0d9cb306d61aa9e42245236da
parente6c479a9f7ed8900bb99cfdff824ef4544c689f9 (diff)
parent9be7d0c3ce3c17cfaab528db7203905eb40c6bf3 (diff)
Merge "Make screenCapture calls to SF async" into main
-rw-r--r--libs/gui/aidl/android/gui/ISurfaceComposer.aidl6
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp116
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h13
3 files changed, 78 insertions, 57 deletions
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 539a1c140e..5e8e9043c1 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -230,20 +230,20 @@ interface ISurfaceComposer {
* The subregion can be optionally rotated. It will also be scaled to
* match the size of the output buffer.
*/
- void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);
+ oneway void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);
/**
* Capture the specified screen. This requires the READ_FRAME_BUFFER
* permission.
*/
- void captureDisplayById(long displayId, IScreenCaptureListener listener);
+ oneway void captureDisplayById(long displayId, IScreenCaptureListener listener);
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
* This requires READ_FRAME_BUFFER permission. This function will fail if there
* is a secure window on screen
*/
- void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
+ oneway void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
/**
* Clears the frame statistics for animations.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ef483f673d..f114b28506 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -7332,16 +7332,27 @@ ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayD
} // namespace
-status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+static void invokeScreenCaptureError(const status_t status,
+ const sp<IScreenCaptureListener>& captureListener) {
+ ScreenCaptureResults captureResults;
+ captureResults.fenceResult = base::unexpected(status);
+ captureListener->onScreenCaptureCompleted(captureResults);
+}
+
+void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
status_t validate = validateScreenshotPermissions(args);
if (validate != OK) {
- return validate;
+ invokeScreenCaptureError(validate, captureListener);
+ return;
}
- if (!args.displayToken) return BAD_VALUE;
+ if (!args.displayToken) {
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
+ }
wp<const DisplayDevice> displayWeak;
ui::LayerStack layerStack;
@@ -7350,7 +7361,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
{
Mutex::Autolock lock(mStateLock);
sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken);
- if (!display) return NAME_NOT_FOUND;
+ if (!display) {
+ invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
+ return;
+ }
displayWeak = display;
layerStack = display->getLayerStack();
@@ -7365,7 +7379,8 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
excludeLayerIds.emplace(excludeLayer);
} else {
ALOGW("Invalid layer handle passed as excludeLayer to captureDisplay");
- return NAME_NOT_FOUND;
+ invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
+ return;
}
}
}
@@ -7388,14 +7403,12 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
}
- auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize,
- args.pixelFormat, args.allowProtected, args.grayscale,
- captureListener);
- return fenceStatus(future.get());
+ captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
+ args.allowProtected, args.grayscale, captureListener);
}
-status_t SurfaceFlinger::captureDisplay(DisplayId displayId,
- const sp<IScreenCaptureListener>& captureListener) {
+void SurfaceFlinger::captureDisplay(DisplayId displayId,
+ const sp<IScreenCaptureListener>& captureListener) {
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
ui::Size size;
@@ -7404,7 +7417,8 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId,
const auto display = getDisplayDeviceLocked(displayId);
if (!display) {
- return NAME_NOT_FOUND;
+ invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
+ return;
}
displayWeak = display;
@@ -7432,25 +7446,25 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId,
if (captureListener == nullptr) {
ALOGE("capture screen must provide a capture listener callback");
- return BAD_VALUE;
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
}
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
- ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale,
- captureListener);
- return fenceStatus(future.get());
+ captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
+ ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener);
}
-status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
status_t validate = validateScreenshotPermissions(args);
if (validate != OK) {
- return validate;
+ invokeScreenCaptureError(validate, captureListener);
+ return;
}
ui::Size reqSize;
@@ -7468,13 +7482,15 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
parent = LayerHandle::getLayer(args.layerHandle);
if (parent == nullptr) {
ALOGE("captureLayers called with an invalid or removed parent");
- return NAME_NOT_FOUND;
+ invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
+ return;
}
if (!canCaptureBlackoutContent &&
parent->getDrawingState().flags & layer_state_t::eLayerSecure) {
ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
- return PERMISSION_DENIED;
+ invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
+ return;
}
Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
@@ -7491,7 +7507,8 @@ status_t 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.
- return BAD_VALUE;
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
}
reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);
@@ -7501,7 +7518,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
excludeLayerIds.emplace(excludeLayer);
} else {
ALOGW("Invalid layer handle passed as excludeLayer to captureLayers");
- return NAME_NOT_FOUND;
+ invokeScreenCaptureError(NAME_NOT_FOUND, captureListener);
+ return;
}
}
} // mStateLock
@@ -7509,7 +7527,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
// really small crop or frameScale
if (reqSize.width <= 0 || reqSize.height <= 0) {
ALOGW("Failed to captureLayes: crop or scale too small");
- return BAD_VALUE;
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
}
bool childrenOnly = args.childrenOnly;
@@ -7573,26 +7592,27 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
if (captureListener == nullptr) {
ALOGE("capture screen must provide a capture listener callback");
- return BAD_VALUE;
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
}
- auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize,
- args.pixelFormat, args.allowProtected, args.grayscale,
- captureListener);
- return fenceStatus(future.get());
+ captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat,
+ args.allowProtected, args.grayscale, captureListener);
}
-ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
- RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots,
- ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale,
- const sp<IScreenCaptureListener>& captureListener) {
+void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
+ GetLayerSnapshotsFunction getLayerSnapshots,
+ ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
+ bool allowProtected, bool grayscale,
+ const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) {
ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32
") that exceeds render target size limit.",
bufferSize.getWidth(), bufferSize.getHeight());
- return ftl::yield<FenceResult>(base::unexpected(BAD_VALUE)).share();
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
}
// Loop over all visible layers to see whether there's any protected layer. A protected layer is
@@ -7632,14 +7652,16 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
// Otherwise an irreponsible process may cause an SF crash by allocating
// too much.
ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
- return ftl::yield<FenceResult>(base::unexpected(bufferStatus)).share();
+ invokeScreenCaptureError(bufferStatus, captureListener);
+ return;
}
const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
renderengine::impl::ExternalTexture::Usage::
WRITEABLE);
- return captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
- false /* regionSampling */, grayscale, captureListener);
+ auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture,
+ false /* regionSampling */, grayscale, captureListener);
+ fence.get();
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon(
@@ -9079,28 +9101,28 @@ binder::Status SurfaceComposerAIDL::setGameContentType(const sp<IBinder>& displa
binder::Status SurfaceComposerAIDL::captureDisplay(
const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
- status_t status = mFlinger->captureDisplay(args, captureListener);
- return binderStatusFromStatusT(status);
+ mFlinger->captureDisplay(args, captureListener);
+ return binderStatusFromStatusT(NO_ERROR);
}
binder::Status SurfaceComposerAIDL::captureDisplayById(
int64_t displayId, const sp<IScreenCaptureListener>& captureListener) {
- status_t status;
+ // status_t status;
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId));
- status = mFlinger->captureDisplay(*id, captureListener);
+ mFlinger->captureDisplay(*id, captureListener);
} else {
- status = PERMISSION_DENIED;
+ invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
}
- return binderStatusFromStatusT(status);
+ return binderStatusFromStatusT(NO_ERROR);
}
binder::Status SurfaceComposerAIDL::captureLayers(
const LayerCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
- status_t status = mFlinger->captureLayers(args, captureListener);
- return binderStatusFromStatusT(status);
+ mFlinger->captureLayers(args, captureListener);
+ return binderStatusFromStatusT(NO_ERROR);
}
binder::Status SurfaceComposerAIDL::overrideHdrTypes(const sp<IBinder>& display,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f61f9a2345..93560bdbcf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -535,9 +535,9 @@ private:
EventRegistrationFlags eventRegistration = {},
const sp<IBinder>& layerHandle = nullptr);
- status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
- status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
- status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
+ void captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
+ void captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
+ void captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*)
@@ -836,10 +836,9 @@ private:
// Boot animation, on/off animations and screen capture
void startBootAnim();
- ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction,
- ui::Size bufferSize, ui::PixelFormat,
- bool allowProtected, bool grayscale,
- const sp<IScreenCaptureListener>&);
+ void captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize,
+ ui::PixelFormat, bool allowProtected, bool grayscale,
+ const sp<IScreenCaptureListener>&);
ftl::SharedFuture<FenceResult> captureScreenCommon(
RenderAreaFuture, GetLayerSnapshotsFunction,
const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,