Added ScreenCaptureListener to allow for screenshot request callbacks
Added boiler plate code to send a listener to the screenshot requests to
allow screenshots to be async.
Test: LayerStateTest
Bug: 162367424
Change-Id: I747e7316364a145bed6a920d72a592e493ca0029
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index b72c854..468cc16 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -234,6 +234,7 @@
"android.gui.IGraphicBufferConsumer",
"android.gui.IRegionSamplingListener",
"android.gui.ITransactionComposerListener",
+ "android.gui.IScreenCaptureListener",
"android.gui.SensorEventConnection",
"android.gui.SensorServer",
"android.hardware.ICamera",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 686e274..9285b23 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -62,6 +62,7 @@
"IGraphicBufferProducer.cpp",
"IProducerListener.cpp",
"IRegionSamplingListener.cpp",
+ "IScreenCaptureListener.cpp",
"ISurfaceComposer.cpp",
"ISurfaceComposerClient.cpp",
"ITransactionCompletedListener.cpp",
diff --git a/libs/gui/IScreenCaptureListener.cpp b/libs/gui/IScreenCaptureListener.cpp
new file mode 100644
index 0000000..0635e9c
--- /dev/null
+++ b/libs/gui/IScreenCaptureListener.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IScreenCaptureListener.h>
+#include <gui/LayerState.h>
+
+namespace android {
+
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+ ON_SCREEN_CAPTURE_COMPLETE = IBinder::FIRST_CALL_TRANSACTION,
+ LAST = ON_SCREEN_CAPTURE_COMPLETE,
+};
+
+} // Anonymous namespace
+
+class BpScreenCaptureListener : public SafeBpInterface<IScreenCaptureListener> {
+public:
+ explicit BpScreenCaptureListener(const sp<IBinder>& impl)
+ : SafeBpInterface<IScreenCaptureListener>(impl, "BpScreenCaptureListener") {}
+
+ ~BpScreenCaptureListener() override;
+
+ status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IScreenCaptureListener::getInterfaceDescriptor());
+
+ SAFE_PARCEL(captureResults.write, data);
+ return remote()->transact(static_cast<uint32_t>(Tag::ON_SCREEN_CAPTURE_COMPLETE), data,
+ &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpScreenCaptureListener::~BpScreenCaptureListener() = default;
+
+IMPLEMENT_META_INTERFACE(ScreenCaptureListener, "android.gui.IScreenCaptureListener");
+
+status_t BnScreenCaptureListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ auto tag = static_cast<Tag>(code);
+ switch (tag) {
+ case Tag::ON_SCREEN_CAPTURE_COMPLETE: {
+ CHECK_INTERFACE(IScreenCaptureListener, data, reply);
+ ScreenCaptureResults captureResults;
+ SAFE_PARCEL(captureResults.read, data);
+ return onScreenCaptureComplete(captureResults);
+ }
+ default: {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+ }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 62f7c23..3b0b392 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -607,19 +607,31 @@
}
status_t ScreenCaptureResults::write(Parcel& output) const {
- SAFE_PARCEL(output.write, *buffer);
+ if (buffer != nullptr) {
+ SAFE_PARCEL(output.writeBool, true);
+ SAFE_PARCEL(output.write, *buffer);
+ } else {
+ SAFE_PARCEL(output.writeBool, false);
+ }
SAFE_PARCEL(output.writeBool, capturedSecureLayers);
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(capturedDataspace));
+ SAFE_PARCEL(output.writeInt32, result);
return NO_ERROR;
}
status_t ScreenCaptureResults::read(const Parcel& input) {
- buffer = new GraphicBuffer();
- SAFE_PARCEL(input.read, *buffer);
+ bool hasGraphicBuffer;
+ SAFE_PARCEL(input.readBool, &hasGraphicBuffer);
+ if (hasGraphicBuffer) {
+ buffer = new GraphicBuffer();
+ SAFE_PARCEL(input.read, *buffer);
+ }
+
SAFE_PARCEL(input.readBool, &capturedSecureLayers);
uint32_t dataspace = 0;
SAFE_PARCEL(input.readUint32, &dataspace);
capturedDataspace = static_cast<ui::Dataspace>(dataspace);
+ SAFE_PARCEL(input.readInt32, &result);
return NO_ERROR;
}
diff --git a/libs/gui/include/gui/IScreenCaptureListener.h b/libs/gui/include/gui/IScreenCaptureListener.h
new file mode 100644
index 0000000..a2ddc9f
--- /dev/null
+++ b/libs/gui/include/gui/IScreenCaptureListener.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/Binder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/SafeInterface.h>
+
+namespace android {
+
+struct ScreenCaptureResults;
+
+// TODO(b/166271443): Convert to AIDL
+class IScreenCaptureListener : public IInterface {
+public:
+ DECLARE_META_INTERFACE(ScreenCaptureListener)
+
+ virtual status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) = 0;
+};
+
+class BnScreenCaptureListener : public SafeBnInterface<IScreenCaptureListener> {
+public:
+ BnScreenCaptureListener()
+ : SafeBnInterface<IScreenCaptureListener>("BnScreenCaptureListener") {}
+
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) override;
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 653d849..47d62fe 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -369,6 +369,7 @@
sp<GraphicBuffer> buffer;
bool capturedSecureLayers{false};
ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB};
+ status_t result = NO_ERROR;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
index 785c2c3..e66df4a 100644
--- a/services/surfaceflinger/tests/LayerState_test.cpp
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -83,6 +83,7 @@
results.buffer = new GraphicBuffer(100, 200, PIXEL_FORMAT_RGBA_8888, 1, 0);
results.capturedSecureLayers = true;
results.capturedDataspace = ui::Dataspace::DISPLAY_P3;
+ results.result = BAD_VALUE;
Parcel p;
results.write(p);
@@ -98,6 +99,7 @@
ASSERT_EQ(results.buffer->getPixelFormat(), results2.buffer->getPixelFormat());
ASSERT_EQ(results.capturedSecureLayers, results2.capturedSecureLayers);
ASSERT_EQ(results.capturedDataspace, results2.capturedDataspace);
+ ASSERT_EQ(results.result, results2.result);
}
} // namespace test