Pass IScreenCaptureListener to screen capture functions
The call is still synchronous but the SF screen capture requests take in
the IScreenCaptureListener object so the results can be sent back
asynchronously.
Test: SurfaceFlinger_test
Test: libgui_test
Bug: 162367424
Change-Id: If20fc69c1bb9eca71f76c151d2aee160a666c506
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2c50acc..0ac493d 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -109,52 +109,33 @@
}
virtual status_t captureDisplay(const DisplayCaptureArgs& args,
- ScreenCaptureResults& captureResults) {
+ const sp<IScreenCaptureListener>& captureListener) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-
SAFE_PARCEL(args.write, data);
- status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("captureDisplay failed to transact: %d", result);
- return result;
- }
+ SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener));
- SAFE_PARCEL(captureResults.read, reply);
- return NO_ERROR;
+ return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
}
virtual status_t captureDisplay(uint64_t displayOrLayerStack,
- ScreenCaptureResults& captureResults) {
+ const sp<IScreenCaptureListener>& captureListener) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeUint64, displayOrLayerStack)
- status_t result =
- remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("captureDisplay failed to transact: %d", result);
- return result;
- }
+ SAFE_PARCEL(data.writeUint64, displayOrLayerStack);
+ SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener));
- SAFE_PARCEL(captureResults.read, reply);
- return NO_ERROR;
+ return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
}
virtual status_t captureLayers(const LayerCaptureArgs& args,
- ScreenCaptureResults& captureResults) {
+ const sp<IScreenCaptureListener>& captureListener) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-
SAFE_PARCEL(args.write, data);
+ SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(captureListener));
- status_t result = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("captureLayers failed to transact: %d", result);
- return result;
- }
-
- SAFE_PARCEL(captureResults.read, reply);
- return NO_ERROR;
+ return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
}
virtual bool authenticateSurfaceTexture(
@@ -1251,37 +1232,29 @@
case CAPTURE_DISPLAY: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
DisplayCaptureArgs args;
- ScreenCaptureResults captureResults;
-
+ sp<IScreenCaptureListener> captureListener;
SAFE_PARCEL(args.read, data);
- status_t res = captureDisplay(args, captureResults);
- if (res == NO_ERROR) {
- SAFE_PARCEL(captureResults.write, *reply);
- }
- return res;
+ SAFE_PARCEL(data.readStrongBinder, &captureListener);
+
+ return captureDisplay(args, captureListener);
}
case CAPTURE_DISPLAY_BY_ID: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
uint64_t displayOrLayerStack = 0;
+ sp<IScreenCaptureListener> captureListener;
SAFE_PARCEL(data.readUint64, &displayOrLayerStack);
- ScreenCaptureResults captureResults;
- status_t res = captureDisplay(displayOrLayerStack, captureResults);
- if (res == NO_ERROR) {
- SAFE_PARCEL(captureResults.write, *reply);
- }
- return res;
+ SAFE_PARCEL(data.readStrongBinder, &captureListener);
+
+ return captureDisplay(displayOrLayerStack, captureListener);
}
case CAPTURE_LAYERS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
LayerCaptureArgs args;
- ScreenCaptureResults captureResults;
-
+ sp<IScreenCaptureListener> captureListener;
SAFE_PARCEL(args.read, data);
- status_t res = captureLayers(args, captureResults);
- if (res == NO_ERROR) {
- SAFE_PARCEL(captureResults.write, *reply);
- }
- return res;
+ SAFE_PARCEL(data.readStrongBinder, &captureListener);
+
+ return captureLayers(args, captureListener);
}
case AUTHENTICATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 62a3c45..65a1a01 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1921,26 +1921,57 @@
}
// ----------------------------------------------------------------------------
+status_t SyncScreenCaptureListener::onScreenCaptureComplete(
+ const ScreenCaptureResults& captureResults) {
+ resultsPromise.set_value(captureResults);
+ return NO_ERROR;
+}
+
+ScreenCaptureResults SyncScreenCaptureListener::waitForResults() {
+ std::future<ScreenCaptureResults> resultsFuture = resultsPromise.get_future();
+ return resultsFuture.get();
+}
status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs,
ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- return s->captureDisplay(captureArgs, captureResults);
+
+ sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t status = s->captureDisplay(captureArgs, captureListener);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ captureResults = captureListener->waitForResults();
+ return captureResults.result;
}
status_t ScreenshotClient::captureDisplay(uint64_t displayOrLayerStack,
ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- return s->captureDisplay(displayOrLayerStack, captureResults);
+
+ sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t status = s->captureDisplay(displayOrLayerStack, captureListener);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ captureResults = captureListener->waitForResults();
+ return captureResults.result;
}
status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs,
ScreenCaptureResults& captureResults) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == nullptr) return NO_INIT;
- return s->captureLayers(captureArgs, captureResults);
+
+ sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t status = s->captureLayers(captureArgs, captureListener);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ captureResults = captureListener->waitForResults();
+ return captureResults.result;
}
} // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e955ea8..e057b68 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -22,6 +22,7 @@
#include <binder/IBinder.h>
#include <binder/IInterface.h>
+#include <gui/IScreenCaptureListener.h>
#include <gui/ITransactionCompletedListener.h>
#include <math/vec4.h>
@@ -255,10 +256,10 @@
* match the size of the output buffer.
*/
virtual status_t captureDisplay(const DisplayCaptureArgs& args,
- ScreenCaptureResults& captureResults) = 0;
+ const sp<IScreenCaptureListener>& captureListener) = 0;
virtual status_t captureDisplay(uint64_t displayOrLayerStack,
- ScreenCaptureResults& captureResults) = 0;
+ const sp<IScreenCaptureListener>& captureListener) = 0;
template <class AA>
struct SpHash {
@@ -271,7 +272,7 @@
* is a secure window on screen
*/
virtual status_t captureLayers(const LayerCaptureArgs& args,
- ScreenCaptureResults& captureResults) = 0;
+ const sp<IScreenCaptureListener>& captureListener) = 0;
/* Clears the frame statistics for animations.
*
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 1a9710a..05151ba 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <future>
#include <set>
#include <unordered_map>
#include <unordered_set>
@@ -593,10 +594,17 @@
// ---------------------------------------------------------------------------
+class SyncScreenCaptureListener : public BnScreenCaptureListener {
+public:
+ status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) override;
+ ScreenCaptureResults waitForResults();
+
+private:
+ std::promise<ScreenCaptureResults> resultsPromise;
+};
+
class ScreenshotClient {
public:
- // if cropping isn't required, callers may pass in a default Rect, e.g.:
- // capture(display, producer, Rect(), reqWidth, ...);
static status_t captureDisplay(const DisplayCaptureArgs& captureArgs,
ScreenCaptureResults& captureResults);
static status_t captureDisplay(uint64_t displayOrLayerStack,
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index d88c477..4a186b1 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -203,6 +203,20 @@
ASSERT_EQ(false, ::testing::Test::HasFailure());
}
+ static status_t captureDisplay(DisplayCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults) {
+ const auto sf = ComposerService::getComposerService();
+ SurfaceComposerClient::Transaction().apply(true);
+
+ const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t status = sf->captureDisplay(captureArgs, captureListener);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ captureResults = captureListener->waitForResults();
+ return captureResults.result;
+ }
+
sp<SurfaceComposerClient> mClient;
sp<ISurfaceComposer> mComposer;
@@ -306,7 +320,7 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
}
@@ -383,7 +397,7 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
@@ -440,7 +454,7 @@
adapter.waitForCallbacks();
// capture screen and verify that it is red
- ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b,
@@ -481,7 +495,7 @@
ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
adapter.waitForCallbacks();
- ASSERT_EQ(NO_ERROR, mComposer->captureDisplay(mCaptureArgs, mCaptureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
switch (tr) {
case ui::Transform::ROT_0:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 9fd8c42..aedba2a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -197,6 +197,20 @@
ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU));
}
+ static status_t captureDisplay(DisplayCaptureArgs& captureArgs,
+ ScreenCaptureResults& captureResults) {
+ const auto sf = ComposerService::getComposerService();
+ SurfaceComposerClient::Transaction().apply(true);
+
+ const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
+ status_t status = sf->captureDisplay(captureArgs, captureListener);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ captureResults = captureListener->waitForResults();
+ return captureResults.result;
+ }
+
sp<Surface> mSurface;
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mSurfaceControl;
@@ -250,7 +264,7 @@
captureArgs.height = 64;
ScreenCaptureResults captureResults;
- ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(captureArgs, captureResults));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
NATIVE_WINDOW_API_CPU));
@@ -280,7 +294,7 @@
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR, sf->captureDisplay(captureArgs, captureResults));
+ ASSERT_EQ(NO_ERROR, captureDisplay(captureArgs, captureResults));
}
TEST_F(SurfaceTest, ConcreteTypeIsSurface) {
@@ -743,7 +757,7 @@
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
ColorMode /*colorMode*/) override { return NO_ERROR; }
status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */,
- ScreenCaptureResults& /* captureResults */) override {
+ const sp<IScreenCaptureListener>& /* captureListener */) override {
return NO_ERROR;
}
status_t getAutoLowLatencyModeSupport(const sp<IBinder>& /*display*/,
@@ -757,11 +771,12 @@
}
void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {}
status_t captureDisplay(uint64_t /*displayOrLayerStack*/,
- ScreenCaptureResults& /* captureResults */) override {
+ const sp<IScreenCaptureListener>& /* captureListener */) override {
return NO_ERROR;
}
- virtual status_t captureLayers(const LayerCaptureArgs& /* captureArgs */,
- ScreenCaptureResults& /* captureResults */) override {
+ virtual status_t captureLayers(
+ const LayerCaptureArgs& /* captureArgs */,
+ const sp<IScreenCaptureListener>& /* captureListener */) override {
return NO_ERROR;
}
status_t clearAnimationFrameStats() override { return NO_ERROR; }