SF: Do not block the main thread on screenshots
The destructor of the future returned by std::async blocks until the
async operation completes, which defeats the purpose of spinning up
a thread to wait on the RenderEngine future. Instead, defer the wait
back to the Binder thread.
Bug: 232436803
Test: Perfetto
Change-Id: I7260002741a0174d8960894d490079757dc4bb5b
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 83e8d3f..d313406 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -6624,24 +6624,21 @@
});
if (captureListener) {
- // TODO: The future returned by std::async blocks the main thread. Return a chain of
- // futures to the Binder thread instead.
- std::async([=]() mutable {
- ATRACE_NAME("captureListener is nonnull!");
- auto fenceResult = renderFuture.get();
- // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult.
- captureResults.result = fenceStatus(fenceResult);
- captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
- captureListener->onScreenCaptureCompleted(captureResults);
- });
+ // Defer blocking on renderFuture back to the Binder thread.
+ return ftl::Future(std::move(renderFuture))
+ .then([captureListener, captureResults = std::move(captureResults)](
+ FenceResult fenceResult) mutable -> FenceResult {
+ // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult.
+ captureResults.result = fenceStatus(fenceResult);
+ captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
+ captureListener->onScreenCaptureCompleted(captureResults);
+ return base::unexpected(NO_ERROR);
+ })
+ .share();
}
return renderFuture;
});
- if (captureListener) {
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
-
// Flatten nested futures.
auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
return future;