Add capture args to captureDisplayById
Test: make && screencap
Change-Id: I509bd458ee2fc712cf1d978caa8dac8d14154045
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a351811..922b0dd 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -3122,12 +3122,12 @@
return statusTFromBinderStatus(status);
}
-status_t ScreenshotClient::captureDisplay(DisplayId displayId,
+status_t ScreenshotClient::captureDisplay(DisplayId displayId, const gui::CaptureArgs& captureArgs,
const sp<IScreenCaptureListener>& captureListener) {
sp<gui::ISurfaceComposer> s(ComposerServiceAIDL::getComposerService());
if (s == nullptr) return NO_INIT;
- binder::Status status = s->captureDisplayById(displayId.value, captureListener);
+ binder::Status status = s->captureDisplayById(displayId.value, captureArgs, captureListener);
return statusTFromBinderStatus(status);
}
diff --git a/libs/gui/aidl/android/gui/CaptureArgs.aidl b/libs/gui/aidl/android/gui/CaptureArgs.aidl
new file mode 100644
index 0000000..920d949
--- /dev/null
+++ b/libs/gui/aidl/android/gui/CaptureArgs.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package android.gui;
+
+parcelable CaptureArgs cpp_header "gui/DisplayCaptureArgs.h";
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index a7cf5dd..265373c 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -16,6 +16,7 @@
package android.gui;
+import android.gui.CaptureArgs;
import android.gui.Color;
import android.gui.CompositionPreference;
import android.gui.ContentSamplingAttributes;
@@ -238,7 +239,8 @@
* Capture the specified screen. This requires the READ_FRAME_BUFFER
* permission.
*/
- oneway void captureDisplayById(long displayId, IScreenCaptureListener listener);
+ oneway void captureDisplayById(long displayId, in CaptureArgs args,
+ IScreenCaptureListener listener);
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index 3142103..065ba06 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -100,8 +100,8 @@
MOCK_METHOD(binder::Status, setGameContentType, (const sp<IBinder>&, bool), (override));
MOCK_METHOD(binder::Status, captureDisplay,
(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
- MOCK_METHOD(binder::Status, captureDisplayById, (int64_t, const sp<IScreenCaptureListener>&),
- (override));
+ MOCK_METHOD(binder::Status, captureDisplayById,
+ (int64_t, const gui::CaptureArgs&, const sp<IScreenCaptureListener>&), (override));
MOCK_METHOD(binder::Status, captureLayers,
(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
MOCK_METHOD(binder::Status, clearAnimationFrameStats, (), (override));
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 54c3aa7..5bf6c47 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -841,8 +841,14 @@
class ScreenshotClient {
public:
static status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
- static status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
+ static status_t captureDisplay(DisplayId, const gui::CaptureArgs&,
+ const sp<IScreenCaptureListener>&);
static status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
+
+ [[deprecated]] static status_t captureDisplay(DisplayId id,
+ const sp<IScreenCaptureListener>& listener) {
+ return captureDisplay(id, gui::CaptureArgs(), listener);
+ }
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 0e26544..8d3eacb 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -786,7 +786,8 @@
return binder::Status::ok();
}
- binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override {
+ binder::Status captureDisplayById(int64_t, const gui::CaptureArgs&,
+ const sp<IScreenCaptureListener>&) override {
return binder::Status::ok();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9c8555e..2dd035b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -7582,7 +7582,7 @@
args.allowProtected, args.grayscale, captureListener);
}
-void SurfaceFlinger::captureDisplay(DisplayId displayId,
+void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
const sp<IScreenCaptureListener>& captureListener) {
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
@@ -7601,10 +7601,23 @@
size = display->getLayerStackSpaceRect().getSize();
}
+ size.width *= args.frameScaleX;
+ size.height *= args.frameScaleY;
+
+ // We could query a real value for this but it'll be a long, long time until we support
+ // displays that need upwards of 1GB per buffer so...
+ constexpr auto kMaxTextureSize = 16384;
+ if (size.width <= 0 || size.height <= 0 || size.width >= kMaxTextureSize ||
+ size.height >= kMaxTextureSize) {
+ ALOGE("capture display resolved to invalid size %d x %d", size.width, size.height);
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
+ }
+
RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- return DisplayRenderArea::create(displayWeak, Rect(), size, ui::Dataspace::UNKNOWN,
+ return DisplayRenderArea::create(displayWeak, Rect(), size, args.dataspace,
false /* useIdentityTransform */,
- false /* hintForSeamlessTransition */,
+ args.hintForSeamlessTransition,
false /* captureSecureLayers */);
});
@@ -7628,8 +7641,8 @@
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
- ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener);
+ captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, args.pixelFormat,
+ kAllowProtected, kGrayscale, captureListener);
}
void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -9423,13 +9436,14 @@
}
binder::Status SurfaceComposerAIDL::captureDisplayById(
- int64_t displayId, const sp<IScreenCaptureListener>& captureListener) {
+ int64_t displayId, const CaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) {
// 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));
- mFlinger->captureDisplay(*id, captureListener);
+ mFlinger->captureDisplay(*id, args, captureListener);
} else {
invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1e90340..9177a5b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -531,7 +531,7 @@
const sp<IBinder>& layerHandle = nullptr);
void captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
- void captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
+ void captureDisplay(DisplayId, const CaptureArgs&, const sp<IScreenCaptureListener>&);
void captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
@@ -1507,7 +1507,8 @@
binder::Status setGameContentType(const sp<IBinder>& display, bool on) override;
binder::Status captureDisplay(const DisplayCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
- binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override;
+ binder::Status captureDisplayById(int64_t, const CaptureArgs&,
+ const sp<IScreenCaptureListener>&) override;
binder::Status captureLayers(const LayerCaptureArgs&,
const sp<IScreenCaptureListener>&) override;