Merge "InputVerifier: verify button events and states (attempt 2)" into main
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index c0c0aae..339ce4b 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -22,17 +22,33 @@
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
#include <cutils/trace.h>
+#include <gtest/gtest-spi.h>
#include <gtest/gtest.h>
#include <utils/CallStack.h>
#include <malloc.h>
+#include <atomic>
#include <functional>
+#include <numeric>
#include <vector>
using namespace android::binder::impl;
static android::String8 gEmpty(""); // make sure first allocation from optimization runs
+struct State {
+ State(std::vector<size_t>&& expectedMallocs) : expectedMallocs(std::move(expectedMallocs)) {}
+ ~State() {
+ size_t num = numMallocs.load();
+ if (expectedMallocs.size() != num) {
+ ADD_FAILURE() << "Expected " << expectedMallocs.size() << " allocations, but got "
+ << num;
+ }
+ }
+ const std::vector<size_t> expectedMallocs;
+ std::atomic<size_t> numMallocs;
+};
+
struct DestructionAction {
DestructionAction(std::function<void()> f) : mF(std::move(f)) {}
~DestructionAction() { mF(); };
@@ -95,8 +111,7 @@
// Action to execute when malloc is hit. Supports nesting. Malloc is not
// restricted when the allocation hook is being processed.
-__attribute__((warn_unused_result))
-DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
+__attribute__((warn_unused_result)) DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
MallocHooks before = MallocHooks::save();
LambdaHooks::lambdas.emplace_back(std::move(f));
LambdaHooks::lambda_malloc_hooks.overwrite();
@@ -106,6 +121,22 @@
});
}
+DestructionAction setExpectedMallocs(std::vector<size_t>&& expected) {
+ auto state = std::make_shared<State>(std::move(expected));
+ return OnMalloc([state = state](size_t bytes) {
+ size_t num = state->numMallocs.fetch_add(1);
+ if (num >= state->expectedMallocs.size() || state->expectedMallocs[num] != bytes) {
+ ADD_FAILURE() << "Unexpected allocation number " << num << " of size " << bytes
+ << " bytes" << std::endl
+ << android::CallStack::stackToString("UNEXPECTED ALLOCATION",
+ android::CallStack::getCurrent(
+ 4 /*ignoreDepth*/)
+ .get())
+ << std::endl;
+ }
+ });
+}
+
// exported symbol, to force compiler not to optimize away pointers we set here
const void* imaginary_use;
@@ -119,16 +150,53 @@
imaginary_use = new int[10];
}
+ delete[] reinterpret_cast<const int*>(imaginary_use);
EXPECT_EQ(mallocs, 1u);
}
+TEST(TestTheTest, OnMallocWithExpectedMallocs) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 8,
+ };
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ }
+}
+
+TEST(TestTheTest, OnMallocWithExpectedMallocsWrongSize) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 100000,
+ };
+ EXPECT_NONFATAL_FAILURE(
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ },
+ "Unexpected allocation number 2 of size 8 bytes");
+}
__attribute__((warn_unused_result))
DestructionAction ScopeDisallowMalloc() {
return OnMalloc([&](size_t bytes) {
- ADD_FAILURE() << "Unexpected allocation: " << bytes;
+ FAIL() << "Unexpected allocation: " << bytes;
using android::CallStack;
- std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION", CallStack::getCurrent(4 /*ignoreDepth*/).get())
+ std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION",
+ CallStack::getCurrent(4 /*ignoreDepth*/).get())
<< std::endl;
});
}
@@ -224,6 +292,51 @@
EXPECT_EQ(mallocs, 1u);
}
+TEST(BinderAccessorAllocation, AddAccessorCheckService) {
+ // Need to call defaultServiceManager() before checking malloc because it
+ // will allocate an instance in the call_once
+ const auto sm = defaultServiceManager();
+ const std::string kInstanceName1 = "foo.bar.IFoo/default";
+ const std::string kInstanceName2 = "foo.bar.IFoo2/default";
+ const String16 kInstanceName16(kInstanceName1.c_str());
+ std::vector<size_t> expectedMallocs = {
+ // addAccessorProvider
+ 112, // new AccessorProvider
+ 16, // new AccessorProviderEntry
+ // checkService
+ 45, // String8 from String16 in CppShim::checkService
+ 128, // writeInterfaceToken
+ 16, // getInjectedAccessor, new AccessorProviderEntry
+ 66, // getInjectedAccessor, String16
+ 45, // String8 from String16 in AccessorProvider::provide
+ };
+ std::set<std::string> supportedInstances = {kInstanceName1, kInstanceName2};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+
+ sp<IBinder> binder = sm->checkService(kInstanceName16);
+
+ status_t status = android::removeAccessorProvider(receipt);
+}
+
+TEST(BinderAccessorAllocation, AddAccessorEmpty) {
+ std::vector<size_t> expectedMallocs = {
+ 48, // From ALOGE with empty set of instances
+ };
+ std::set<std::string> supportedInstances = {};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+
+ EXPECT_TRUE(receipt.expired());
+}
+
TEST(RpcBinderAllocation, SetupRpcServer) {
std::string tmp = getenv("TMPDIR") ?: "/tmp";
std::string addr = tmp + "/binderRpcBenchmark";
@@ -255,6 +368,7 @@
}
int main(int argc, char** argv) {
+ LOG(INFO) << "Priming static log variables for binderAllocationLimits.";
if (getenv("LIBC_HOOKS_ENABLE") == nullptr) {
CHECK(0 == setenv("LIBC_HOOKS_ENABLE", "1", true /*overwrite*/));
execv(argv[0], argv);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index c1ddb6a..9793800 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -5530,7 +5530,7 @@
LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
<< " in display %" << displayId;
cancellations.emplace_back(touchedWindow.windowHandle,
- CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt);
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
// Since we are about to drop the touch, cancel the events for the wallpaper as well.
if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
touchedWindow.windowHandle->getInfo()->inputConfig.test(
@@ -5838,52 +5838,33 @@
{ // acquire lock
std::scoped_lock _l(mLock);
- // Find the target touch state and touched window by fromToken.
- auto [state, touchedWindow, displayId] =
- findTouchStateWindowAndDisplay(fromToken, mTouchStates.mTouchStatesByDisplay);
+ ScopedSyntheticEventTracer traceContext(mTracer);
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "transferring touch from this window to another window",
+ traceContext.getTracker());
- if (state == nullptr || touchedWindow == nullptr) {
- ALOGD("Touch transfer failed because from window is not being touched.");
- return false;
- }
- std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
- if (deviceIds.size() != 1) {
- LOG(INFO) << "Can't transfer touch. Currently touching devices: "
- << dumpContainer(deviceIds) << " for window: " << touchedWindow->dump();
- return false;
- }
- const DeviceId deviceId = *deviceIds.begin();
-
- const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
- const sp<WindowInfoHandle> toWindowHandle =
- mWindowInfos.findWindowHandle(toToken, displayId);
- if (!toWindowHandle) {
- ALOGW("Cannot transfer touch because the transfer target window was not found.");
+ auto result = mTouchStates.transferTouchGesture(fromToken, toToken, mWindowInfos,
+ mConnectionManager);
+ if (!result.has_value()) {
return false;
}
- if (DEBUG_FOCUS) {
- ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
- touchedWindow->windowHandle->getName().c_str(),
- toWindowHandle->getName().c_str());
+ const auto [toWindowHandle, deviceId, pointers, cancellations, pointerDowns] =
+ result.value();
+
+ for (const auto& cancellationArgs : cancellations) {
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.deviceId.has_value());
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
}
- // Erase old window.
- ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
- std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers(deviceId);
- state->removeWindowByToken(fromToken);
-
- // Add new window.
- nsecs_t downTimeInTarget = now();
- ftl::Flags<InputTarget::Flags> newTargetFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT);
- if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
- newTargetFlags |= InputTarget::Flags::FOREGROUND;
+ for (const auto& pointerDownArgs : pointerDowns) {
+ synthesizePointerDownEventsForConnectionLocked(pointerDownArgs.downTimeInTarget,
+ pointerDownArgs.connection,
+ pointerDownArgs.targetFlags,
+ traceContext.getTracker());
}
- // Transferring touch focus using this API should not effect the focused window.
- newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
- state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
- deviceId, pointers, downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -5896,30 +5877,6 @@
const size_t id = pointers.begin()->id;
mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id);
}
-
- // Synthesize cancel for old window and down for new window.
- ScopedSyntheticEventTracer traceContext(mTracer);
- std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
- std::shared_ptr<Connection> toConnection = mConnectionManager.getConnection(toToken);
- if (fromConnection != nullptr && toConnection != nullptr) {
- fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "transferring touch from this window to another window",
- traceContext.getTracker());
- synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
-
- // Check if the wallpaper window should deliver the corresponding event.
- transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
- *state, deviceId, pointers, traceContext.getTracker());
-
- // Because new window may have a wallpaper window, it will merge input state from it
- // parent window, after this the firstNewPointerIdx in input state will be reset, then
- // it will cause new move event be thought inconsistent, so we should synthesize the
- // down event after it reset.
- synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
- newTargetFlags,
- traceContext.getTracker());
- }
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
@@ -5927,6 +5884,85 @@
return true;
}
+std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
+ std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>>
+InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken,
+ const sp<android::IBinder>& toToken,
+ const DispatcherWindowInfo& windowInfos,
+ const ConnectionManager& connections) {
+ // Find the target touch state and touched window by fromToken.
+ auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken);
+ if (!touchStateWindowAndDisplay.has_value()) {
+ ALOGD("Touch transfer failed because from window is not being touched.");
+ return std::nullopt;
+ }
+
+ auto [state, touchedWindow, displayId] = touchStateWindowAndDisplay.value();
+ std::set<DeviceId> deviceIds = touchedWindow.getTouchingDeviceIds();
+ if (deviceIds.size() != 1) {
+ LOG(INFO) << "Can't transfer touch. Currently touching devices: "
+ << dumpContainer(deviceIds) << " for window: " << touchedWindow.dump();
+ return std::nullopt;
+ }
+ const DeviceId deviceId = *deviceIds.begin();
+
+ const sp<WindowInfoHandle> fromWindowHandle = touchedWindow.windowHandle;
+ const sp<WindowInfoHandle> toWindowHandle = windowInfos.findWindowHandle(toToken, displayId);
+ if (!toWindowHandle) {
+ ALOGW("Cannot transfer touch because the transfer target window was not found.");
+ return std::nullopt;
+ }
+
+ if (DEBUG_FOCUS) {
+ ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
+ fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
+ }
+
+ // Erase old window.
+ ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow.targetFlags;
+ std::vector<PointerProperties> pointers = touchedWindow.getTouchingPointers(deviceId);
+ state.removeWindowByToken(fromToken);
+
+ // Add new window.
+ nsecs_t downTimeInTarget = now();
+ ftl::Flags<InputTarget::Flags> newTargetFlags = oldTargetFlags & (InputTarget::Flags::SPLIT);
+ if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
+ newTargetFlags |= InputTarget::Flags::FOREGROUND;
+ }
+ // Transferring touch focus using this API should not effect the focused window.
+ newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
+ state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
+ deviceId, pointers, downTimeInTarget);
+
+ // Synthesize cancel for old window and down for new window.
+ std::shared_ptr<Connection> fromConnection = connections.getConnection(fromToken);
+ std::shared_ptr<Connection> toConnection = connections.getConnection(toToken);
+ std::list<CancellationArgs> cancellations;
+ std::list<PointerDownArgs> pointerDowns;
+ if (fromConnection != nullptr && toConnection != nullptr) {
+ fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
+ cancellations.emplace_back(fromWindowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+
+ // Check if the wallpaper window should deliver the corresponding event.
+ auto [wallpaperCancellations, wallpaperPointerDowns] =
+ transferWallpaperTouch(fromWindowHandle, toWindowHandle, state, deviceId, pointers,
+ oldTargetFlags, newTargetFlags, windowInfos, connections);
+
+ cancellations.splice(cancellations.end(), wallpaperCancellations);
+ pointerDowns.splice(pointerDowns.end(), wallpaperPointerDowns);
+
+ // Because new window may have a wallpaper window, it will merge input state from it
+ // parent window, after this the firstNewPointerIdx in input state will be reset, then
+ // it will cause new move event be thought inconsistent, so we should synthesize the
+ // down event after it reset.
+ pointerDowns.emplace_back(downTimeInTarget, toConnection, newTargetFlags);
+ }
+
+ return std::make_tuple(toWindowHandle, deviceId, pointers, cancellations, pointerDowns);
+}
+
/**
* Get the touched foreground window on the given display.
* Return null if there are no windows touched on that display, or if more than one foreground
@@ -6259,43 +6295,62 @@
return BAD_VALUE;
}
- auto [statePtr, windowPtr, displayId] =
- findTouchStateWindowAndDisplay(token, mTouchStates.mTouchStatesByDisplay);
- if (statePtr == nullptr || windowPtr == nullptr) {
+ ScopedSyntheticEventTracer traceContext(mTracer);
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "input channel stole pointer stream", traceContext.getTracker());
+ const auto result = mTouchStates.pilferPointers(token, *requestingConnection);
+ if (!result.ok()) {
+ return result.error().code();
+ }
+
+ const auto cancellations = *result;
+ for (const auto& cancellationArgs : cancellations) {
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+ options.displayId = cancellationArgs.displayId;
+ options.deviceId = cancellationArgs.deviceId;
+ options.pointerIds = cancellationArgs.pointerIds;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
+ }
+ return OK;
+}
+
+base::Result<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>, status_t>
+InputDispatcher::DispatcherTouchState::pilferPointers(const sp<IBinder>& token,
+ const Connection& requestingConnection) {
+ auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(token);
+ if (!touchStateWindowAndDisplay.has_value()) {
LOG(WARNING)
<< "Attempted to pilfer points from a channel without any on-going pointer streams."
" Ignoring.";
- return BAD_VALUE;
- }
- std::set<int32_t> deviceIds = windowPtr->getTouchingDeviceIds();
- if (deviceIds.empty()) {
- LOG(WARNING) << "Can't pilfer: no touching devices in window: " << windowPtr->dump();
- return BAD_VALUE;
+ return Error(BAD_VALUE);
}
- ScopedSyntheticEventTracer traceContext(mTracer);
+ auto [state, window, displayId] = touchStateWindowAndDisplay.value();
+
+ std::set<int32_t> deviceIds = window.getTouchingDeviceIds();
+ if (deviceIds.empty()) {
+ LOG(WARNING) << "Can't pilfer: no touching devices in window: " << window.dump();
+ return Error(BAD_VALUE);
+ }
+
+ std::list<CancellationArgs> cancellations;
for (const DeviceId deviceId : deviceIds) {
- TouchState& state = *statePtr;
- TouchedWindow& window = *windowPtr;
// Send cancel events to all the input channels we're stealing from.
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "input channel stole pointer stream", traceContext.getTracker());
- options.deviceId = deviceId;
- options.displayId = displayId;
std::vector<PointerProperties> pointers = window.getTouchingPointers(deviceId);
std::bitset<MAX_POINTER_ID + 1> pointerIds = getPointerIds(pointers);
- options.pointerIds = pointerIds;
-
std::string canceledWindows;
for (const TouchedWindow& w : state.windows) {
if (w.windowHandle->getToken() != token) {
- synthesizeCancelationEventsForWindowLocked(w.windowHandle, options);
+ cancellations.emplace_back(w.windowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ deviceId, displayId, pointerIds);
canceledWindows += canceledWindows.empty() ? "[" : ", ";
canceledWindows += w.windowHandle->getName();
}
}
canceledWindows += canceledWindows.empty() ? "[]" : "]";
- LOG(INFO) << "Channel " << requestingConnection->getInputChannelName()
+ LOG(INFO) << "Channel " << requestingConnection.getInputChannelName()
<< " is stealing input gesture for device " << deviceId << " from "
<< canceledWindows;
@@ -6305,7 +6360,7 @@
state.cancelPointersForWindowsExcept(deviceId, pointerIds, token);
}
- return OK;
+ return cancellations;
}
void InputDispatcher::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
@@ -7158,12 +7213,15 @@
}
}
-void InputDispatcher::transferWallpaperTouch(
+std::pair<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
+ std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>
+InputDispatcher::DispatcherTouchState::transferWallpaperTouch(
+ const sp<gui::WindowInfoHandle> fromWindowHandle,
+ const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
+ android::DeviceId deviceId, const std::vector<PointerProperties>& pointers,
ftl::Flags<InputTarget::Flags> oldTargetFlags,
- ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<WindowInfoHandle> fromWindowHandle,
- const sp<WindowInfoHandle> toWindowHandle, TouchState& state, DeviceId deviceId,
- const std::vector<PointerProperties>& pointers,
- const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
+ ftl::Flags<InputTarget::Flags> newTargetFlags, const DispatcherWindowInfo& windowInfos,
+ const ConnectionManager& connections) {
const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
fromWindowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -7174,16 +7232,16 @@
const sp<WindowInfoHandle> oldWallpaper =
oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
- newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(toWindowHandle) : nullptr;
+ newHasWallpaper ? windowInfos.findWallpaperWindowBelow(toWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
- return;
+ return {};
}
+ std::list<CancellationArgs> cancellations;
+ std::list<PointerDownArgs> pointerDowns;
if (oldWallpaper != nullptr) {
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "transferring touch focus to another window", traceTracker);
state.removeWindowByToken(oldWallpaper->getToken());
- synthesizeCancelationEventsForWindowLocked(oldWallpaper, options);
+ cancellations.emplace_back(oldWallpaper, CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
}
if (newWallpaper != nullptr) {
@@ -7195,15 +7253,16 @@
state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
deviceId, pointers, downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
- mConnectionManager.getConnection(newWallpaper->getToken());
+ connections.getConnection(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
std::shared_ptr<Connection> toConnection =
- mConnectionManager.getConnection(toWindowHandle->getToken());
+ connections.getConnection(toWindowHandle->getToken());
toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
- synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
- wallpaperFlags, traceTracker);
+ pointerDowns.emplace_back(downTimeInTarget, wallpaperConnection, wallpaperFlags);
}
+ pointerDowns.emplace_back(downTimeInTarget, wallpaperConnection, wallpaperFlags);
}
+ return {cancellations, pointerDowns};
}
sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWallpaperWindowBelow(
@@ -7457,4 +7516,17 @@
mTouchStatesByDisplay.clear();
}
+std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
+InputDispatcher::DispatcherTouchState::findTouchStateWindowAndDisplay(
+ const sp<android::IBinder>& token) {
+ for (auto& [displayId, state] : mTouchStatesByDisplay) {
+ for (TouchedWindow& w : state.windows) {
+ if (w.windowHandle->getToken() == token) {
+ return std::make_tuple(std::ref(state), std::ref(w), displayId);
+ }
+ }
+ }
+ return std::nullopt;
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index f590806..f214131 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -355,7 +355,15 @@
struct CancellationArgs {
const sp<gui::WindowInfoHandle> windowHandle;
CancelationOptions::Mode mode;
- std::optional<DeviceId> deviceId;
+ std::optional<DeviceId> deviceId{std::nullopt};
+ ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
+ std::bitset<MAX_POINTER_ID + 1> pointerIds{};
+ };
+
+ struct PointerDownArgs {
+ const nsecs_t downTimeInTarget;
+ const std::shared_ptr<Connection> connection;
+ const ftl::Flags<InputTarget::Flags> targetFlags;
};
static void addPointerWindowTarget(const sp<android::gui::WindowInfoHandle>& windowHandle,
@@ -387,17 +395,40 @@
std::string dump() const;
// Updates the touchState for display from WindowInfo,
- // return vector of CancellationArgs for every cancelled touch
+ // returns list of CancellationArgs for every cancelled touch
std::list<CancellationArgs> updateFromWindowInfo(ui::LogicalDisplayId displayId,
const DispatcherWindowInfo& windowInfos);
void removeAllPointersForDevice(DeviceId deviceId);
+ // transfer touch between provided tokens, returns destination WindowHandle, deviceId,
+ // pointers, list of cancelled windows and pointers on successful transfer.
+ std::optional<
+ std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
+ std::list<CancellationArgs>, std::list<PointerDownArgs>>>
+ transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
+ const DispatcherWindowInfo& windowInfos,
+ const ConnectionManager& connections);
+
+ base::Result<std::list<CancellationArgs>, status_t> pilferPointers(
+ const sp<IBinder>& token, const Connection& requestingConnection);
+
void clear();
std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;
private:
+ std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
+ findTouchStateWindowAndDisplay(const sp<IBinder>& token);
+
+ std::pair<std::list<CancellationArgs>, std::list<PointerDownArgs>> transferWallpaperTouch(
+ const sp<gui::WindowInfoHandle> fromWindowHandle,
+ const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
+ DeviceId deviceId, const std::vector<PointerProperties>& pointers,
+ ftl::Flags<InputTarget::Flags> oldTargetFlags,
+ ftl::Flags<InputTarget::Flags> newTargetFlags,
+ const DispatcherWindowInfo& windowInfos, const ConnectionManager& connections);
+
static std::list<CancellationArgs> eraseRemovedWindowsFromWindowInfo(
TouchState& state, ui::LogicalDisplayId displayId,
const DispatcherWindowInfo& windowInfos);
@@ -849,15 +880,6 @@
sp<InputReporterInterface> mReporter;
- void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
- ftl::Flags<InputTarget::Flags> newTargetFlags,
- const sp<android::gui::WindowInfoHandle> fromWindowHandle,
- const sp<android::gui::WindowInfoHandle> toWindowHandle,
- TouchState& state, DeviceId deviceId,
- const std::vector<PointerProperties>& pointers,
- const std::unique_ptr<trace::EventTrackerInterface>& traceTracker)
- REQUIRES(mLock);
-
/** Stores the value of the input flag for per device input latency metrics. */
const bool mPerDeviceInputLatencyMetricsFlag =
com::android::input::flags::enable_per_device_input_latency_metrics();
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index ea7d6d7..88ff370 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -206,7 +206,6 @@
"Display/DisplayModeController.cpp",
"Display/DisplaySnapshot.cpp",
"DisplayDevice.cpp",
- "DisplayRenderArea.cpp",
"Effects/Daltonizer.cpp",
"FpsReporter.cpp",
"FrameTracer/FrameTracer.cpp",
@@ -225,12 +224,10 @@
"Layer.cpp",
"LayerFE.cpp",
"LayerProtoHelper.cpp",
- "LayerRenderArea.cpp",
"LayerVector.cpp",
"NativeWindowSurface.cpp",
"RefreshRateOverlay.cpp",
"RegionSamplingThread.cpp",
- "RenderArea.cpp",
"Scheduler/EventThread.cpp",
"Scheduler/FrameRateOverrideMappings.cpp",
"Scheduler/LayerHistory.cpp",
diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp
deleted file mode 100644
index c63c738..0000000
--- a/services/surfaceflinger/DisplayRenderArea.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-#include "DisplayRenderArea.h"
-#include "DisplayDevice.h"
-
-namespace android {
-
-std::unique_ptr<RenderArea> DisplayRenderArea::create(wp<const DisplayDevice> displayWeak,
- const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options) {
- if (auto display = displayWeak.promote()) {
- // Using new to access a private constructor.
- return std::unique_ptr<DisplayRenderArea>(new DisplayRenderArea(std::move(display),
- sourceCrop, reqSize,
- reqDataSpace, options));
- }
- return nullptr;
-}
-
-DisplayRenderArea::DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop,
- ui::Size reqSize, ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options)
- : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, options),
- mDisplay(std::move(display)),
- mSourceCrop(sourceCrop) {}
-
-const ui::Transform& DisplayRenderArea::getTransform() const {
- return mTransform;
-}
-
-bool DisplayRenderArea::isSecure() const {
- return mOptions.test(Options::CAPTURE_SECURE_LAYERS) && mDisplay->isSecure();
-}
-
-sp<const DisplayDevice> DisplayRenderArea::getDisplayDevice() const {
- return mDisplay;
-}
-
-Rect DisplayRenderArea::getSourceCrop() const {
- // use the projected display viewport by default.
- if (mSourceCrop.isEmpty()) {
- return mDisplay->getLayerStackSpaceRect();
- }
- return mSourceCrop;
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/DisplayRenderArea.h b/services/surfaceflinger/DisplayRenderArea.h
deleted file mode 100644
index 677d019..0000000
--- a/services/surfaceflinger/DisplayRenderArea.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include "RenderArea.h"
-
-namespace android {
-
-class DisplayDevice;
-
-class DisplayRenderArea : public RenderArea {
-public:
- static std::unique_ptr<RenderArea> create(wp<const DisplayDevice>, const Rect& sourceCrop,
- ui::Size reqSize, ui::Dataspace,
- ftl::Flags<Options> options);
-
- const ui::Transform& getTransform() const override;
- bool isSecure() const override;
- sp<const DisplayDevice> getDisplayDevice() const override;
- Rect getSourceCrop() const override;
-
-private:
- DisplayRenderArea(sp<const DisplayDevice>, const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace, ftl::Flags<Options> options);
-
- const sp<const DisplayDevice> mDisplay;
- const Rect mSourceCrop;
- const ui::Transform mTransform;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
deleted file mode 100644
index bfe6d2a..0000000
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include "DisplayDevice.h"
-#include "FrontEnd/LayerCreationArgs.h"
-#include "Layer.h"
-#include "LayerRenderArea.h"
-#include "SurfaceFlinger.h"
-
-namespace android {
-
-LayerRenderArea::LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot,
- const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- const ui::Transform& layerTransform, const Rect& layerBufferSize,
- ftl::Flags<RenderArea::Options> options)
- : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, options),
- mLayer(std::move(layer)),
- mLayerSnapshot(std::move(layerSnapshot)),
- mLayerBufferSize(layerBufferSize),
- mCrop(crop),
- mTransform(layerTransform) {}
-
-const ui::Transform& LayerRenderArea::getTransform() const {
- return mTransform;
-}
-
-bool LayerRenderArea::isSecure() const {
- return mOptions.test(Options::CAPTURE_SECURE_LAYERS);
-}
-
-sp<const DisplayDevice> LayerRenderArea::getDisplayDevice() const {
- return nullptr;
-}
-
-Rect LayerRenderArea::getSourceCrop() const {
- if (mCrop.isEmpty()) {
- // TODO this should probably be mBounds instead of just buffer bounds
- return mLayerBufferSize;
- } else {
- return mCrop;
- }
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
deleted file mode 100644
index f72c7c7..0000000
--- a/services/surfaceflinger/LayerRenderArea.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 <string>
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-#include <utils/StrongPointer.h>
-
-#include "RenderArea.h"
-
-namespace android {
-
-class DisplayDevice;
-class Layer;
-class SurfaceFlinger;
-
-class LayerRenderArea : public RenderArea {
-public:
- LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop,
- ui::Size reqSize, ui::Dataspace reqDataSpace,
- const ui::Transform& layerTransform, const Rect& layerBufferSize,
- ftl::Flags<RenderArea::Options> options);
-
- const ui::Transform& getTransform() const override;
- bool isSecure() const override;
- sp<const DisplayDevice> getDisplayDevice() const override;
- Rect getSourceCrop() const override;
-
- sp<Layer> getParentLayer() const override { return mLayer; }
- const frontend::LayerSnapshot* getLayerSnapshot() const override { return &mLayerSnapshot; }
-
-private:
- const sp<Layer> mLayer;
- const frontend::LayerSnapshot mLayerSnapshot;
- const Rect mLayerBufferSize;
- const Rect mCrop;
-
- ui::Transform mTransform;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index d3483b0..1c4a11a 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -39,11 +39,8 @@
#include <string>
#include "DisplayDevice.h"
-#include "DisplayRenderArea.h"
#include "FrontEnd/LayerCreationArgs.h"
#include "Layer.h"
-#include "RenderAreaBuilder.h"
-#include "Scheduler/VsyncController.h"
#include "SurfaceFlinger.h"
namespace android {
@@ -259,6 +256,7 @@
ui::LayerStack layerStack;
ui::Transform::RotationFlags orientation;
ui::Size displaySize;
+ Rect layerStackSpaceRect;
{
// TODO(b/159112860): Don't keep sp<DisplayDevice> outside of SF main thread
@@ -267,6 +265,7 @@
layerStack = display->getLayerStack();
orientation = ui::Transform::toRotationFlags(display->getOrientation());
displaySize = display->getSize();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
}
std::vector<RegionSamplingThread::Descriptor> descriptors;
@@ -347,16 +346,20 @@
constexpr bool kGrayscale = false;
constexpr bool kIsProtected = false;
- SurfaceFlinger::RenderAreaBuilderVariant
- renderAreaBuilder(std::in_place_type<DisplayRenderAreaBuilder>, sampledBounds,
- sampledBounds.getSize(), ui::Dataspace::V0_SRGB, displayWeak,
- RenderArea::Options::CAPTURE_SECURE_LAYERS);
+ SurfaceFlinger::ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.sourceCrop = sampledBounds.isEmpty() ? layerStackSpaceRect : sampledBounds;
+ screenshotArgs.reqSize = sampledBounds.getSize();
+ screenshotArgs.dataspace = ui::Dataspace::V0_SRGB;
+ screenshotArgs.isSecure = true;
+ screenshotArgs.seamlessTransition = false;
std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
auto displayState =
- mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
+ mFlinger.getSnapshotsFromMainThread(screenshotArgs, getLayerSnapshotsFn, layers);
FenceResult fenceResult =
- mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling, kGrayscale,
+ mFlinger.captureScreenshot(screenshotArgs, buffer, kRegionSampling, kGrayscale,
kIsProtected, nullptr, displayState, layers)
.get();
if (fenceResult.ok()) {
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
deleted file mode 100644
index 5fea521..0000000
--- a/services/surfaceflinger/RenderArea.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2017 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 "RenderArea.h"
-
-namespace android {
-
-float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
- switch(captureFill) {
- case CaptureFill::CLEAR:
- return 0.0f;
- case CaptureFill::OPAQUE:
- default:
- return 1.0f;
- }
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
deleted file mode 100644
index aa66ccf..0000000
--- a/services/surfaceflinger/RenderArea.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#pragma once
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include <functional>
-
-#include "FrontEnd/LayerSnapshot.h"
-#include "Layer.h"
-
-namespace android {
-
-class DisplayDevice;
-
-// RenderArea describes a rectangular area that layers can be rendered to.
-//
-// There is a logical render area and a physical render area. When a layer is
-// rendered to the render area, it is first transformed and clipped to the logical
-// render area. The transformed and clipped layer is then projected onto the
-// physical render area.
-class RenderArea {
-public:
- enum class CaptureFill {CLEAR, OPAQUE};
- enum class Options {
- // If not set, the secure layer would be blacked out or skipped
- // when rendered to an insecure render area
- CAPTURE_SECURE_LAYERS = 1 << 0,
-
- // If set, the render result may be used for system animations
- // that must preserve the exact colors of the display
- HINT_FOR_SEAMLESS_TRANSITION = 1 << 1,
- };
- static float getCaptureFillValue(CaptureFill captureFill);
-
- RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options)
- : mOptions(options),
- mReqSize(reqSize),
- mReqDataSpace(reqDataSpace),
- mCaptureFill(captureFill) {}
-
- virtual ~RenderArea() = default;
-
- // Returns true if the render area is secure. A secure layer should be
- // blacked out / skipped when rendered to an insecure render area.
- virtual bool isSecure() const = 0;
-
- // Returns the transform to be applied on layers to transform them into
- // the logical render area.
- virtual const ui::Transform& getTransform() const = 0;
-
- // Returns the source crop of the render area. The source crop defines
- // how layers are projected from the logical render area onto the physical
- // render area. It can be larger than the logical render area. It can
- // also be optionally rotated.
- //
- // The source crop is specified in layer space (when rendering a layer and
- // its children), or in layer-stack space (when rendering all layers visible
- // on the display).
- virtual Rect getSourceCrop() const = 0;
-
- // Returns the size of the physical render area.
- int getReqWidth() const { return mReqSize.width; }
- int getReqHeight() const { return mReqSize.height; }
-
- // Returns the composition data space of the render area.
- ui::Dataspace getReqDataSpace() const { return mReqDataSpace; }
-
- // Returns the fill color of the physical render area. Regions not
- // covered by any rendered layer should be filled with this color.
- CaptureFill getCaptureFill() const { return mCaptureFill; }
-
- virtual sp<const DisplayDevice> getDisplayDevice() const = 0;
-
- // If this is a LayerRenderArea, return the root layer of the
- // capture operation.
- virtual sp<Layer> getParentLayer() const { return nullptr; }
-
- // If this is a LayerRenderArea, return the layer snapshot
- // of the root layer of the capture operation
- virtual const frontend::LayerSnapshot* getLayerSnapshot() const { return nullptr; }
-
- // Returns whether the render result may be used for system animations that
- // must preserve the exact colors of the display.
- bool getHintForSeamlessTransition() const {
- return mOptions.test(Options::HINT_FOR_SEAMLESS_TRANSITION);
- }
-
-protected:
- ftl::Flags<Options> mOptions;
-
-private:
- const ui::Size mReqSize;
- const ui::Dataspace mReqDataSpace;
- const CaptureFill mCaptureFill;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/RenderAreaBuilder.h b/services/surfaceflinger/RenderAreaBuilder.h
deleted file mode 100644
index 599fa7e..0000000
--- a/services/surfaceflinger/RenderAreaBuilder.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2024 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 "DisplayDevice.h"
-#include "DisplayRenderArea.h"
-#include "LayerRenderArea.h"
-#include "ui/Size.h"
-#include "ui/Transform.h"
-
-namespace android {
-/**
- * A parameter object for creating a render area
- */
-struct RenderAreaBuilder {
- // Source crop of the render area
- Rect crop;
-
- // Size of the physical render area
- ui::Size reqSize;
-
- // Composition data space of the render area
- ui::Dataspace reqDataSpace;
-
- ftl::Flags<RenderArea::Options> options;
- virtual std::unique_ptr<RenderArea> build() const = 0;
-
- RenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- ftl::Flags<RenderArea::Options> options)
- : crop(crop), reqSize(reqSize), reqDataSpace(reqDataSpace), options(options) {}
-
- virtual ~RenderAreaBuilder() = default;
-};
-
-struct DisplayRenderAreaBuilder : RenderAreaBuilder {
- DisplayRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- wp<const DisplayDevice> displayWeak,
- ftl::Flags<RenderArea::Options> options)
- : RenderAreaBuilder(crop, reqSize, reqDataSpace, options), displayWeak(displayWeak) {}
-
- // Display that render area will be on
- wp<const DisplayDevice> displayWeak;
-
- std::unique_ptr<RenderArea> build() const override {
- return DisplayRenderArea::create(displayWeak, crop, reqSize, reqDataSpace, options);
- }
-};
-
-struct LayerRenderAreaBuilder : RenderAreaBuilder {
- LayerRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, sp<Layer> layer,
- bool childrenOnly, ftl::Flags<RenderArea::Options> options)
- : RenderAreaBuilder(crop, reqSize, reqDataSpace, options),
- layer(layer),
- childrenOnly(childrenOnly) {}
-
- // Root layer of the render area
- sp<Layer> layer;
-
- // Layer snapshot of the root layer
- frontend::LayerSnapshot layerSnapshot;
-
- // Transform to be applied on the layers to transform them
- // into the logical render area
- ui::Transform layerTransform{ui::Transform()};
-
- // Buffer bounds
- Rect layerBufferSize{Rect()};
-
- // If false, transform is inverted from the parent snapshot
- bool childrenOnly;
-
- // Uses parent snapshot to determine layer transform and buffer size
- void setLayerSnapshot(const frontend::LayerSnapshot& parentSnapshot) {
- layerSnapshot = parentSnapshot;
- if (!childrenOnly) {
- layerTransform = parentSnapshot.localTransform.inverse();
- }
- layerBufferSize = parentSnapshot.bufferSize;
- }
-
- std::unique_ptr<RenderArea> build() const override {
- return std::make_unique<LayerRenderArea>(layer, std::move(layerSnapshot), crop, reqSize,
- reqDataSpace, layerTransform, layerBufferSize,
- options);
- }
-};
-
-} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index 5f71b88..7123905 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -29,11 +29,15 @@
std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) {
std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
- ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&,
+ ScreenCaptureOutput, compositionengine::CompositionEngine,
+ /* sourceCrop */ const Rect, std::optional<DisplayId>,
const compositionengine::Output::ColorProfile&,
- bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling,
- args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping);
- output->editState().isSecure = args.renderArea.isSecure();
+ /* layerAlpha */ float,
+ /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop, args.displayId,
+ args.colorProfile, args.layerAlpha, args.regionSampling,
+ args.dimInGammaSpaceForEnhancedScreenshots,
+ args.enableLocalTonemapping);
+ output->editState().isSecure = args.isSecure;
output->editState().isProtected = args.isProtected;
output->setCompositionEnabled(true);
output->setLayerFilter({args.layerStack});
@@ -47,16 +51,16 @@
.setHasWideColorGamut(true)
.Build()));
- const Rect& sourceCrop = args.renderArea.getSourceCrop();
+ const Rect& sourceCrop = args.sourceCrop;
const ui::Rotation orientation = ui::ROTATION_0;
output->setDisplaySize({sourceCrop.getWidth(), sourceCrop.getHeight()});
output->setProjection(orientation, sourceCrop,
- {args.renderArea.getReqWidth(), args.renderArea.getReqHeight()});
+ {args.reqBufferSize.width, args.reqBufferSize.height});
{
std::string name = args.regionSampling ? "RegionSampling" : "ScreenCaptureOutput";
- if (auto displayDevice = args.renderArea.getDisplayDevice()) {
- base::StringAppendF(&name, " for %" PRIu64, displayDevice->getId().value);
+ if (args.displayId) {
+ base::StringAppendF(&name, " for %" PRIu64, args.displayId.value().value);
}
output->setName(name);
}
@@ -64,11 +68,14 @@
}
ScreenCaptureOutput::ScreenCaptureOutput(
- const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile,
+ const Rect sourceCrop, std::optional<DisplayId> displayId,
+ const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha,
bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
bool enableLocalTonemapping)
- : mRenderArea(renderArea),
+ : mSourceCrop(sourceCrop),
+ mDisplayId(displayId),
mColorProfile(colorProfile),
+ mLayerAlpha(layerAlpha),
mRegionSampling(regionSampling),
mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots),
mEnableLocalTonemapping(enableLocalTonemapping) {}
@@ -83,7 +90,7 @@
const std::shared_ptr<renderengine::ExternalTexture>& buffer) const {
auto clientCompositionDisplay =
compositionengine::impl::Output::generateClientCompositionDisplaySettings(buffer);
- clientCompositionDisplay.clip = mRenderArea.getSourceCrop();
+ clientCompositionDisplay.clip = mSourceCrop;
auto renderIntent = static_cast<ui::RenderIntent>(clientCompositionDisplay.renderIntent);
if (mDimInGammaSpaceForEnhancedScreenshots && renderIntent != ui::RenderIntent::COLORIMETRIC &&
@@ -130,8 +137,8 @@
}
std::vector<aidl::android::hardware::graphics::composer3::Luts> luts;
- if (auto displayDevice = mRenderArea.getDisplayDevice()) {
- const auto id = PhysicalDisplayId::tryCast(displayDevice->getId());
+ if (mDisplayId) {
+ const auto id = PhysicalDisplayId::tryCast(mDisplayId.value());
if (id) {
auto& hwc = getCompositionEngine().getHwComposer();
hwc.getLuts(*id, buffers, &luts);
@@ -201,14 +208,15 @@
}
}
- Rect sourceCrop = mRenderArea.getSourceCrop();
compositionengine::LayerFE::LayerSettings fillLayer;
fillLayer.source.buffer.buffer = nullptr;
fillLayer.source.solidColor = half3(0.0f, 0.0f, 0.0f);
fillLayer.geometry.boundaries =
- FloatRect(static_cast<float>(sourceCrop.left), static_cast<float>(sourceCrop.top),
- static_cast<float>(sourceCrop.right), static_cast<float>(sourceCrop.bottom));
- fillLayer.alpha = half(RenderArea::getCaptureFillValue(mRenderArea.getCaptureFill()));
+ FloatRect(static_cast<float>(mSourceCrop.left), static_cast<float>(mSourceCrop.top),
+ static_cast<float>(mSourceCrop.right),
+ static_cast<float>(mSourceCrop.bottom));
+
+ fillLayer.alpha = half(mLayerAlpha);
clientCompositionLayers.insert(clientCompositionLayers.begin(), fillLayer);
return clientCompositionLayers;
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
index 444a28f..b3e98b1 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -22,23 +22,25 @@
#include <ui/Rect.h>
#include <unordered_map>
-#include "RenderArea.h"
-
namespace android {
struct ScreenCaptureOutputArgs {
const compositionengine::CompositionEngine& compositionEngine;
const compositionengine::Output::ColorProfile& colorProfile;
- const RenderArea& renderArea;
ui::LayerStack layerStack;
+ Rect sourceCrop;
std::shared_ptr<renderengine::ExternalTexture> buffer;
+ std::optional<DisplayId> displayId;
+ ui::Size reqBufferSize;
float sdrWhitePointNits;
float displayBrightnessNits;
// Counterintuitively, when targetBrightness > 1.0 then dim the scene.
float targetBrightness;
+ float layerAlpha;
bool regionSampling;
bool treat170mAsSrgb;
bool dimInGammaSpaceForEnhancedScreenshots;
+ bool isSecure = false;
bool isProtected = false;
bool enableLocalTonemapping = false;
};
@@ -49,10 +51,10 @@
// SurfaceFlinger::captureLayers and SurfaceFlinger::captureDisplay.
class ScreenCaptureOutput : public compositionengine::impl::Output {
public:
- ScreenCaptureOutput(const RenderArea& renderArea,
+ ScreenCaptureOutput(const Rect sourceCrop, std::optional<DisplayId> displayId,
const compositionengine::Output::ColorProfile& colorProfile,
- bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
- bool enableLocalTonemapping);
+ float layerAlpha, bool regionSampling,
+ bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping);
void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
@@ -67,8 +69,10 @@
private:
std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> generateLuts();
- const RenderArea& mRenderArea;
+ const Rect mSourceCrop;
+ const std::optional<DisplayId> mDisplayId;
const compositionengine::Output::ColorProfile& mColorProfile;
+ const float mLayerAlpha;
const bool mRegionSampling;
const bool mDimInGammaSpaceForEnhancedScreenshots;
const bool mEnableLocalTonemapping;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index eecdd72..1dc7b2e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -137,7 +137,6 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
-#include "DisplayRenderArea.h"
#include "Effects/Daltonizer.h"
#include "FpsReporter.h"
#include "FrameTimeline/FrameTimeline.h"
@@ -151,14 +150,12 @@
#include "Jank/JankTracker.h"
#include "Layer.h"
#include "LayerProtoHelper.h"
-#include "LayerRenderArea.h"
#include "LayerVector.h"
#include "MutexUtils.h"
#include "NativeWindowSurface.h"
#include "PowerAdvisor/PowerAdvisor.h"
#include "PowerAdvisor/Workload.h"
#include "RegionSamplingThread.h"
-#include "RenderAreaBuilder.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
@@ -7220,9 +7217,13 @@
}
wp<const DisplayDevice> displayWeak;
+ DisplayId displayId;
ui::LayerStack layerStack;
ui::Size reqSize(args.width, args.height);
std::unordered_set<uint32_t> excludeLayerIds;
+ Rect layerStackSpaceRect;
+ bool displayIsSecure;
+
{
Mutex::Autolock lock(mStateLock);
sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken);
@@ -7232,11 +7233,14 @@
return;
}
displayWeak = display;
+ displayId = display->getId();
layerStack = display->getLayerStack();
+ displayIsSecure = display->isSecure();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
// set the requested width/height to the logical display layer stack rect size by default
if (args.width == 0 || args.height == 0) {
- reqSize = display->getLayerStackSpaceRect().getSize();
+ reqSize = layerStackSpaceRect.getSize();
}
for (const auto& handle : captureArgs.excludeHandles) {
@@ -7255,16 +7259,19 @@
getLayerSnapshotsForScreenshots(layerStack, captureArgs.uid,
std::move(excludeLayerIds));
- ftl::Flags<RenderArea::Options> options;
- if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (captureArgs.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- gui::aidl_utils::fromARect(captureArgs.sourceCrop),
- reqSize,
- static_cast<ui::Dataspace>(captureArgs.dataspace),
- displayWeak, options),
- getLayerSnapshotsFn, reqSize,
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = displayId;
+ screenshotArgs.sourceCrop = gui::aidl_utils::fromARect(captureArgs.sourceCrop);
+ if (screenshotArgs.sourceCrop.isEmpty()) {
+ screenshotArgs.sourceCrop = layerStackSpaceRect;
+ }
+ screenshotArgs.reqSize = reqSize;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(captureArgs.dataspace);
+ screenshotArgs.isSecure = captureArgs.captureSecureLayers && displayIsSecure;
+ screenshotArgs.seamlessTransition = captureArgs.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, reqSize,
static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
@@ -7274,6 +7281,9 @@
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
ui::Size size;
+ Rect layerStackSpaceRect;
+ bool displayIsSecure;
+
{
Mutex::Autolock lock(mStateLock);
@@ -7286,7 +7296,9 @@
displayWeak = display;
layerStack = display->getLayerStack();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
size = display->getLayerStackSpaceRect().getSize();
+ displayIsSecure = display->isSecure();
}
size.width *= args.frameScaleX;
@@ -7315,15 +7327,18 @@
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- ftl::Flags<RenderArea::Options> options;
- if (args.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- Rect(), size,
- static_cast<ui::Dataspace>(args.dataspace),
- displayWeak, options),
- getLayerSnapshotsFn, size, static_cast<ui::PixelFormat>(args.pixelFormat),
- kAllowProtected, kGrayscale, captureListener);
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = displayId;
+ screenshotArgs.sourceCrop = layerStackSpaceRect;
+ screenshotArgs.reqSize = size;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(args.dataspace);
+ screenshotArgs.isSecure = args.captureSecureLayers && displayIsSecure;
+ screenshotArgs.seamlessTransition = args.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, size,
+ static_cast<ui::PixelFormat>(args.pixelFormat), kAllowProtected, kGrayscale,
+ captureListener);
}
ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) {
@@ -7425,14 +7440,16 @@
return;
}
- ftl::Flags<RenderArea::Options> options;
- if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (captureArgs.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop,
- reqSize, dataspace, parent, args.childrenOnly,
- options),
- getLayerSnapshotsFn, reqSize,
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = parent->getSequence();
+ screenshotArgs.childrenOnly = args.childrenOnly;
+ screenshotArgs.sourceCrop = crop;
+ screenshotArgs.reqSize = reqSize;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(captureArgs.dataspace);
+ screenshotArgs.isSecure = captureArgs.captureSecureLayers;
+ screenshotArgs.seamlessTransition = captureArgs.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, reqSize,
static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
@@ -7468,10 +7485,10 @@
// is reduced when grabbed from the main thread, thus also reducing
// risk of deadlocks.
std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getSnapshotsFromMainThread(
- RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ ScreenshotArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn,
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
return mScheduler
- ->schedule([=, this, &renderAreaBuilder, &layers]() REQUIRES(kMainThreadContext) {
+ ->schedule([=, this, &args, &layers]() REQUIRES(kMainThreadContext) {
SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Screenshot");
mPowerAdvisor->setScreenshotWorkload();
SFTRACE_NAME("getSnapshotsFromMainThread");
@@ -7486,12 +7503,12 @@
ui::INVALID_LAYER_STACK);
}
}
- return getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
+ return getDisplayStateOnMainThread(args);
})
.get();
}
-void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder,
+void SurfaceFlinger::captureScreenCommon(ScreenshotArgs& args,
GetLayerSnapshotsFunction getLayerSnapshotsFn,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
bool allowProtected, bool grayscale,
@@ -7507,7 +7524,11 @@
}
std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
- auto displayState = getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layers);
+ auto displayState = getSnapshotsFromMainThread(args, getLayerSnapshotsFn, layers);
+ if (!displayState) {
+ ALOGD("Display state not found");
+ invokeScreenCaptureError(NO_MEMORY, captureListener);
+ }
const bool hasHdrLayer = std::any_of(layers.cbegin(), layers.cend(), [this](const auto& layer) {
return isHdrLayer(*(layer.second->mSnapshot.get()));
@@ -7545,12 +7566,8 @@
std::shared_ptr<renderengine::impl::ExternalTexture> hdrTexture;
std::shared_ptr<renderengine::impl::ExternalTexture> gainmapTexture;
- bool hintForSeamless = std::visit(
- [](auto&& arg) {
- return arg.options.test(RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION);
- },
- renderAreaBuilder);
- if (hasHdrLayer && !hintForSeamless && FlagManager::getInstance().true_hdr_screenshots()) {
+ if (hasHdrLayer && !args.seamlessTransition &&
+ FlagManager::getInstance().true_hdr_screenshots()) {
const auto hdrBuffer =
getFactory().createGraphicBuffer(buffer->getWidth(), buffer->getHeight(),
HAL_PIXEL_FORMAT_RGBA_FP16, 1 /* layerCount */,
@@ -7583,35 +7600,41 @@
}
}
- auto futureFence = captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */,
- grayscale, isProtected, captureListener, displayState,
- layers, hdrTexture, gainmapTexture);
+ auto futureFence =
+ captureScreenshot(args, texture, false /* regionSampling */, grayscale, isProtected,
+ captureListener, displayState, layers, hdrTexture, gainmapTexture);
futureFence.get();
}
-std::optional<SurfaceFlinger::OutputCompositionState>
-SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& renderAreaBuilder) {
+std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getDisplayStateOnMainThread(
+ ScreenshotArgs& args) {
sp<const DisplayDevice> display = nullptr;
{
Mutex::Autolock lock(mStateLock);
- if (auto* layerRenderAreaBuilder =
- std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) {
+ // Screenshot initiated through captureLayers
+ if (auto* layerSequence = std::get_if<int32_t>(&args.captureTypeVariant)) {
// LayerSnapshotBuilder should only be accessed from the main thread.
const frontend::LayerSnapshot* snapshot =
- mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence());
+ mLayerSnapshotBuilder.getSnapshot(*layerSequence);
if (!snapshot) {
- ALOGW("Couldn't find layer snapshot for %d",
- layerRenderAreaBuilder->layer->getSequence());
+ ALOGW("Couldn't find layer snapshot for %d", *layerSequence);
} else {
- layerRenderAreaBuilder->setLayerSnapshot(*snapshot);
+ if (!args.childrenOnly) {
+ args.transform = snapshot->localTransform.inverse();
+ }
+ if (args.sourceCrop.isEmpty()) {
+ args.sourceCrop = snapshot->bufferSize;
+ }
display = findDisplay(
[layerStack = snapshot->outputFilter.layerStack](const auto& display) {
return display.getLayerStack() == layerStack;
});
}
- } else if (auto* displayRenderAreaBuilder =
- std::get_if<DisplayRenderAreaBuilder>(&renderAreaBuilder)) {
- display = displayRenderAreaBuilder->displayWeak.promote();
+
+ // Screenshot initiated through captureDisplay
+ } else if (auto* displayWeak =
+ std::get_if<wp<const DisplayDevice>>(&args.captureTypeVariant)) {
+ display = displayWeak->promote();
}
if (display == nullptr) {
@@ -7626,9 +7649,9 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
- const RenderAreaBuilderVariant& renderAreaBuilder,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener,
+ const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ bool regionSampling, bool grayscale, bool isProtected,
+ const sp<IScreenCaptureListener>& captureListener,
const std::optional<OutputCompositionState>& displayState,
const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
const std::shared_ptr<renderengine::ExternalTexture>& hdrBuffer,
@@ -7636,18 +7659,6 @@
SFTRACE_CALL();
ScreenCaptureResults captureResults;
- std::unique_ptr<const RenderArea> renderArea =
- std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
- renderAreaBuilder);
-
- if (!renderArea) {
- ALOGW("Skipping screen capture because of invalid render area.");
- if (captureListener) {
- captureResults.fenceResult = base::unexpected(NO_MEMORY);
- captureListener->onScreenCaptureCompleted(captureResults);
- }
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
float displayBrightnessNits = displayState.value().displayBrightnessNits;
float sdrWhitePointNits = displayState.value().sdrWhitePointNits;
@@ -7656,8 +7667,8 @@
if (hdrBuffer && gainmapBuffer) {
ftl::SharedFuture<FenceResult> hdrRenderFuture =
- renderScreenImpl(std::move(renderArea), hdrBuffer, regionSampling, grayscale,
- isProtected, captureResults, displayState, layers);
+ renderScreenImpl(args, hdrBuffer, regionSampling, grayscale, isProtected,
+ captureResults, displayState, layers);
captureResults.buffer = buffer->getBuffer();
captureResults.optionalGainMap = gainmapBuffer->getBuffer();
@@ -7680,8 +7691,8 @@
})
.share();
} else {
- renderFuture = renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale,
- isProtected, captureResults, displayState, layers);
+ renderFuture = renderScreenImpl(args, buffer, regionSampling, grayscale, isProtected,
+ captureResults, displayState, layers);
}
if (captureListener) {
@@ -7701,8 +7712,7 @@
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- std::unique_ptr<const RenderArea> renderArea,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
const std::optional<OutputCompositionState>& displayState,
const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
@@ -7713,29 +7723,27 @@
captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure);
captureResults.capturedHdrLayers |= isHdrLayer(*snapshot);
layerFE->mSnapshot->geomLayerTransform =
- renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform;
+ args.transform * layerFE->mSnapshot->geomLayerTransform;
layerFE->mSnapshot->geomInverseLayerTransform =
layerFE->mSnapshot->geomLayerTransform.inverse();
}
auto capturedBuffer = buffer;
- auto requestedDataspace = renderArea->getReqDataSpace();
- auto parent = renderArea->getParentLayer();
auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
auto sdrWhitePointNits = DisplayDevice::sDefaultMaxLumiance;
auto displayBrightnessNits = DisplayDevice::sDefaultMaxLumiance;
- captureResults.capturedDataspace = requestedDataspace;
+ captureResults.capturedDataspace = args.dataspace;
- const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() &&
- !renderArea->getHintForSeamlessTransition();
+ const bool enableLocalTonemapping =
+ FlagManager::getInstance().local_tonemap_screenshots() && !args.seamlessTransition;
if (displayState) {
const auto& state = displayState.value();
captureResults.capturedDataspace =
- pickBestDataspace(requestedDataspace, state, captureResults.capturedHdrLayers,
- renderArea->getHintForSeamlessTransition());
+ pickBestDataspace(args.dataspace, state, captureResults.capturedHdrLayers,
+ args.seamlessTransition);
sdrWhitePointNits = state.sdrWhitePointNits;
if (!captureResults.capturedHdrLayers) {
@@ -7747,7 +7755,7 @@
// Otherwise for seamless transitions it's important to match the current
// display state as the buffer will be shown under these same conditions, and we
// want to avoid any flickers
- if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) {
+ if (sdrWhitePointNits > 1.0f && !args.seamlessTransition) {
// Restrict the amount of HDR "headroom" in the screenshot to avoid
// over-dimming the SDR portion. 2.0 chosen by experimentation
constexpr float kMaxScreenshotHeadroom = 2.0f;
@@ -7758,8 +7766,7 @@
}
// Screenshots leaving the device should be colorimetric
- if (requestedDataspace == ui::Dataspace::UNKNOWN &&
- renderArea->getHintForSeamlessTransition()) {
+ if (args.dataspace == ui::Dataspace::UNKNOWN && args.seamlessTransition) {
renderIntent = state.renderIntent;
}
}
@@ -7774,7 +7781,7 @@
auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace,
sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected, layers,
- layerStack, regionSampling, renderArea = std::move(renderArea), renderIntent,
+ layerStack, regionSampling, args, renderIntent,
enableLocalTonemapping]() -> FenceResult {
std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
mFactory.createCompositionEngine();
@@ -7810,23 +7817,33 @@
}
}
+ // Capturing screenshots using layers have a clear capture fill (0 alpha).
+ // Capturing via display or displayId, which do not use args.layerSequence,
+ // has an opaque capture fill (1 alpha).
+ const float layerAlpha =
+ std::holds_alternative<int32_t>(args.captureTypeVariant) ? 0.0f : 1.0f;
+
// Screenshots leaving the device must not dim in gamma space.
- const bool dimInGammaSpaceForEnhancedScreenshots = mDimInGammaSpaceForEnhancedScreenshots &&
- renderArea->getHintForSeamlessTransition();
+ const bool dimInGammaSpaceForEnhancedScreenshots =
+ mDimInGammaSpaceForEnhancedScreenshots && args.seamlessTransition;
std::shared_ptr<ScreenCaptureOutput> output = createScreenCaptureOutput(
ScreenCaptureOutputArgs{.compositionEngine = *compositionEngine,
.colorProfile = colorProfile,
- .renderArea = *renderArea,
.layerStack = layerStack,
+ .sourceCrop = args.sourceCrop,
.buffer = std::move(buffer),
+ .displayId = args.displayId,
+ .reqBufferSize = args.reqSize,
.sdrWhitePointNits = sdrWhitePointNits,
.displayBrightnessNits = displayBrightnessNits,
.targetBrightness = targetBrightness,
+ .layerAlpha = layerAlpha,
.regionSampling = regionSampling,
.treat170mAsSrgb = mTreat170mAsSrgb,
.dimInGammaSpaceForEnhancedScreenshots =
dimInGammaSpaceForEnhancedScreenshots,
+ .isSecure = args.isSecure,
.isProtected = isProtected,
.enableLocalTonemapping = enableLocalTonemapping});
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b3a3aad..935a2da 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -132,7 +132,6 @@
class MessageBase;
class RefreshRateOverlay;
class RegionSamplingThread;
-class RenderArea;
class TimeStats;
class FrameTracer;
class ScreenCapturer;
@@ -197,9 +196,6 @@
Always,
};
-struct DisplayRenderAreaBuilder;
-struct LayerRenderAreaBuilder;
-
using DisplayColorSetting = compositionengine::OutputColorSetting;
class SurfaceFlinger : public BnSurfaceComposer,
@@ -371,9 +367,7 @@
friend class Layer;
friend class RefreshRateOverlay;
friend class RegionSamplingThread;
- friend class LayerRenderArea;
friend class SurfaceComposerAIDL;
- friend class DisplayRenderArea;
// For unit tests
friend class TestableSurfaceFlinger;
@@ -382,7 +376,6 @@
using TransactionSchedule = scheduler::TransactionSchedule;
using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>;
- using RenderAreaBuilderVariant = std::variant<DisplayRenderAreaBuilder, LayerRenderAreaBuilder>;
using DumpArgs = Vector<String16>;
using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
@@ -868,20 +861,56 @@
using OutputCompositionState = compositionengine::impl::OutputCompositionState;
+ /*
+ * Parameters used across screenshot methods.
+ */
+ struct ScreenshotArgs {
+ // Contains the sequence ID of the parent layer if the screenshot is
+ // initiated though captureLayers(), or the display that the render
+ // result will be on if initiated through captureDisplay()
+ std::variant<int32_t, wp<const DisplayDevice>> captureTypeVariant;
+
+ // Display ID of the display the result will be on
+ std::optional<DisplayId> displayId{std::nullopt};
+
+ // If true, transform is inverted from the parent layer snapshot
+ bool childrenOnly{false};
+
+ // Source crop of the render area
+ Rect sourceCrop;
+
+ // Transform to be applied on the layers to transform them
+ // into the logical render area
+ ui::Transform transform;
+
+ // Size of the physical render area
+ ui::Size reqSize;
+
+ // Composition dataspace of the render area
+ ui::Dataspace dataspace;
+
+ // If false, the secure layer is blacked out or skipped
+ // when rendered to an insecure render area
+ bool isSecure{false};
+
+ // If true, the render result may be used for system animations
+ // that must preserve the exact colors of the display
+ bool seamlessTransition{false};
+ };
+
std::optional<OutputCompositionState> getSnapshotsFromMainThread(
- RenderAreaBuilderVariant& renderAreaBuilder,
- GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ ScreenshotArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn,
std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
- void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
- ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
- bool grayscale, const sp<IScreenCaptureListener>&);
+ void captureScreenCommon(ScreenshotArgs& args, GetLayerSnapshotsFunction, ui::Size bufferSize,
+ ui::PixelFormat, bool allowProtected, bool grayscale,
+ const sp<IScreenCaptureListener>&);
- std::optional<OutputCompositionState> getDisplayStateFromRenderAreaBuilder(
- RenderAreaBuilderVariant& renderAreaBuilder) REQUIRES(kMainThreadContext);
+ std::optional<OutputCompositionState> getDisplayStateOnMainThread(ScreenshotArgs& args)
+ REQUIRES(kMainThreadContext);
ftl::SharedFuture<FenceResult> captureScreenshot(
- const RenderAreaBuilderVariant& renderAreaBuilder,
+ const ScreenshotArgs& args,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener,
const std::optional<OutputCompositionState>& displayState,
@@ -890,8 +919,7 @@
const std::shared_ptr<renderengine::ExternalTexture>& gainmapBuffer = nullptr);
ftl::SharedFuture<FenceResult> renderScreenImpl(
- std::unique_ptr<const RenderArea> renderArea,
- const std::shared_ptr<renderengine::ExternalTexture>&,
+ const ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>&,
bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&,
const std::optional<OutputCompositionState>& displayState,
const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 71cafbf..9ece312 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -36,7 +36,6 @@
#include <system/window.h>
#include <utils/String8.h>
-#include "DisplayRenderArea.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
@@ -199,25 +198,21 @@
const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
constexpr bool regionSampling = false;
- auto renderArea =
- DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(),
- ui::Dataspace::V0_SRGB,
- RenderArea::Options::CAPTURE_SECURE_LAYERS |
- RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION);
-
auto getLayerSnapshotsFn = mFlinger.getLayerSnapshotsForScreenshotsFn(mDisplay->getLayerStack(),
CaptureArgs::UNSET_UID);
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
mCaptureScreenBuffer =
- std::make_shared<renderengine::mock::FakeExternalTexture>(renderArea->getReqWidth(),
- renderArea->getReqHeight(),
+ std::make_shared<renderengine::mock::FakeExternalTexture>(sourceCrop.getSize().width,
+ sourceCrop.getSize().height,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
usage);
- auto future = mFlinger.renderScreenImpl(mDisplay, std::move(renderArea), getLayerSnapshotsFn,
- mCaptureScreenBuffer, regionSampling);
+ auto future = mFlinger.renderScreenImpl(mDisplay, sourceCrop, ui::Dataspace::V0_SRGB,
+ getLayerSnapshotsFn, mCaptureScreenBuffer,
+ regionSampling, mDisplay->isSecure(),
+ /* seamlessTransition */ true);
ASSERT_TRUE(future.valid());
const auto fenceResult = future.get();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2353ef8..9a2e254 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -42,7 +42,6 @@
#include "FrontEnd/RequestedLayerState.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
-#include "RenderArea.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/VSyncTracker.h"
#include "Scheduler/VsyncController.h"
@@ -461,11 +460,11 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto renderScreenImpl(const sp<DisplayDevice> display,
- std::unique_ptr<const RenderArea> renderArea,
+ auto renderScreenImpl(const sp<DisplayDevice> display, const Rect sourceCrop,
+ ui::Dataspace dataspace,
SurfaceFlinger::GetLayerSnapshotsFunction getLayerSnapshotsFn,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool regionSampling) {
+ bool regionSampling, bool isSecure, bool seamlessTransition) {
Mutex::Autolock lock(mFlinger->mStateLock);
ftl::FakeGuard guard(kMainThreadContext);
@@ -473,7 +472,16 @@
auto displayState = std::optional{display->getCompositionDisplay()->getState()};
auto layers = getLayerSnapshotsFn();
- return mFlinger->renderScreenImpl(std::move(renderArea), buffer, regionSampling,
+ SurfaceFlinger::ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = display;
+ screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.sourceCrop = sourceCrop;
+ screenshotArgs.reqSize = sourceCrop.getSize();
+ screenshotArgs.dataspace = dataspace;
+ screenshotArgs.isSecure = isSecure;
+ screenshotArgs.seamlessTransition = seamlessTransition;
+
+ return mFlinger->renderScreenImpl(screenshotArgs, buffer, regionSampling,
false /* grayscale */, false /* isProtected */,
captureResults, displayState, layers);
}