Merge "Fix category names for perfetto api" into main
diff --git a/include/input/DisplayTopologyGraph.h b/include/input/DisplayTopologyGraph.h
index f3f5148..3ae865a 100644
--- a/include/input/DisplayTopologyGraph.h
+++ b/include/input/DisplayTopologyGraph.h
@@ -42,7 +42,9 @@
*/
struct DisplayTopologyAdjacentDisplay {
ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
+ // Position of the adjacent display, relative to the source display.
DisplayTopologyPosition position;
+ // The offset in DP of the adjacent display, relative to the source display.
float offsetDp;
};
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index e88e3f3..170b2ad 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -2771,7 +2771,9 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
+#ifndef __ANDROID__
__android_log_set_logger(__android_log_stderr_logger);
+#endif
return RUN_ALL_TESTS();
}
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index aef9464..0084b9a 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -100,7 +100,9 @@
};
int main(int argc, char* argv[]) {
+#ifndef __ANDROID__
__android_log_set_logger(__android_log_stderr_logger);
+#endif
LOG_ALWAYS_FATAL_IF(argc != 3, "Invalid number of arguments: %d", argc);
unique_fd writeEnd(atoi(argv[1]));
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 9f91285..3140dc8 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "PointerChoreographer"
#include <android-base/logging.h>
+#include <android/configuration.h>
#include <com_android_input_flags.h>
#if defined(__ANDROID__)
#include <gui/SurfaceComposerClient.h>
@@ -114,6 +115,17 @@
}
}
+// The standardised medium display density for which 1 px = 1 dp
+constexpr int32_t DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM;
+
+inline float pxToDp(int px, int dpi) {
+ return static_cast<float>(px * DENSITY_MEDIUM) / static_cast<float>(dpi);
+}
+
+inline int dpToPx(float dp, int dpi) {
+ return static_cast<int>((dp * dpi) / DENSITY_MEDIUM);
+}
+
} // namespace
// --- PointerChoreographer ---
@@ -385,8 +397,7 @@
pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
pc.setDisplayViewport(destinationViewport);
vec2 destinationPosition =
- calculatePositionOnDestinationViewport(destinationViewport,
- cursorOffset - destinationOffset,
+ calculatePositionOnDestinationViewport(destinationViewport, destinationOffset,
sourceBoundary);
// Transform position back to un-rotated coordinate space before sending it to controller
@@ -990,10 +1001,10 @@
return ConstructorDelegate(std::move(ctor));
}
-std::optional<std::pair<const DisplayViewport*, float /*offset*/>>
+std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
const DisplayTopologyPosition sourceBoundary,
- float cursorOffset) const {
+ int32_t sourceCursorOffsetPx) const {
const auto& sourceNode = mTopology.graph.find(sourceDisplayId);
if (sourceNode == mTopology.graph.end()) {
// Topology is likely out of sync with viewport info, wait for it to be updated
@@ -1004,22 +1015,32 @@
if (adjacentDisplay.position != sourceBoundary) {
continue;
}
- const DisplayViewport* destinationViewport =
- findViewportByIdLocked(adjacentDisplay.displayId);
- if (destinationViewport == nullptr) {
+ const DisplayViewport* adjacentViewport = findViewportByIdLocked(adjacentDisplay.displayId);
+ if (adjacentViewport == nullptr) {
// Topology is likely out of sync with viewport info, wait for them to be updated
LOG(WARNING) << "Cannot find viewport for adjacent display "
<< adjacentDisplay.displayId << "of source display " << sourceDisplayId;
continue;
}
- // target position must be within target display boundary
- const int32_t edgeSize = sourceBoundary == DisplayTopologyPosition::TOP ||
+ // As displays can have different densities we need to do all calculations in
+ // density-independent-pixels a.k.a. dp values.
+ const int sourceDensity = mTopology.displaysDensity.at(sourceDisplayId);
+ const int adjacentDisplayDensity = mTopology.displaysDensity.at(adjacentDisplay.displayId);
+ const float sourceCursorOffsetDp = pxToDp(sourceCursorOffsetPx, sourceDensity);
+ const int32_t edgeSizePx = sourceBoundary == DisplayTopologyPosition::TOP ||
sourceBoundary == DisplayTopologyPosition::BOTTOM
- ? (destinationViewport->logicalRight - destinationViewport->logicalLeft)
- : (destinationViewport->logicalBottom - destinationViewport->logicalTop);
- if (cursorOffset >= adjacentDisplay.offsetDp &&
- cursorOffset <= adjacentDisplay.offsetDp + edgeSize) {
- return std::make_pair(destinationViewport, adjacentDisplay.offsetDp);
+ ? (adjacentViewport->logicalRight - adjacentViewport->logicalLeft)
+ : (adjacentViewport->logicalBottom - adjacentViewport->logicalTop);
+ const float adjacentEdgeSizeDp = pxToDp(edgeSizePx, adjacentDisplayDensity);
+ // Target position must be within target display boundary.
+ // Cursor should also be able to cross displays when only display corners are touching and
+ // there may be zero overlapping pixels. To accommodate this we have margin of one pixel
+ // around the end of the overlapping edge.
+ if (sourceCursorOffsetDp >= adjacentDisplay.offsetDp &&
+ sourceCursorOffsetDp <= adjacentDisplay.offsetDp + adjacentEdgeSizeDp) {
+ const int destinationOffsetPx =
+ dpToPx(sourceCursorOffsetDp - adjacentDisplay.offsetDp, adjacentDisplayDensity);
+ return std::make_pair(adjacentViewport, destinationOffsetPx);
}
}
return std::nullopt;
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index c2f5ec0..a9d971a 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -163,10 +163,10 @@
void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
REQUIRES(getLock());
- std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
- const ui::LogicalDisplayId sourceDisplayId,
- const DisplayTopologyPosition sourceBoundary, float cursorOffset) const
- REQUIRES(getLock());
+ std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
+ findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayTopologyPosition sourceBoundary,
+ int32_t sourceCursorOffsetPx) const REQUIRES(getLock());
/* Topology is initialized with default-constructed value, which is an empty topology. Till we
* receive setDisplayTopology call.
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 098019f..56be2e6 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1267,8 +1267,9 @@
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
// The event is stale. However, only drop stale events if there isn't an ongoing
// gesture. That would allow us to complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
+ const auto touchStateIt =
+ mTouchStates.mTouchStatesByDisplay.find(motionEntry->displayId);
+ if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
!touchState.hasHoveringPointers(motionEntry->deviceId)) {
@@ -1355,7 +1356,8 @@
// Alternatively, maybe there's a spy window that could handle this event.
const std::vector<sp<WindowInfoHandle>> touchedSpies =
mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus,
- motionEntry.deviceId, mTouchStatesByDisplay);
+ motionEntry.deviceId,
+ mTouchStates.mTouchStatesByDisplay);
for (const auto& windowHandle : touchedSpies) {
const std::shared_ptr<Connection> connection =
mConnectionManager.getConnection(windowHandle->getToken());
@@ -1480,15 +1482,16 @@
return nullptr;
}
-std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const {
+std::vector<InputTarget> InputDispatcher::DispatcherTouchState::findOutsideTargets(
+ ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos, std::function<void()> dump) {
if (touchedWindow == nullptr) {
return {};
}
// Traverse windows from front to back until we encounter the touched window.
std::vector<InputTarget> outsideTargets;
- const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId);
+ const auto& windowHandles = windowInfos.getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
if (windowHandle == touchedWindow) {
// Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window
@@ -1500,9 +1503,13 @@
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
+ DispatcherTouchState::addPointerWindowTarget(windowHandle,
+ InputTarget::DispatchMode::OUTSIDE,
+ ftl::Flags<InputTarget::Flags>(),
+ pointerIds,
+ /*firstDownTimeInTarget=*/std::nullopt,
+ connections, windowInfos, dump,
+ outsideTargets);
}
}
return outsideTargets;
@@ -1709,7 +1716,7 @@
synthesizeCancelationEventsForAllConnectionsLocked(options);
// Remove all active pointers from this device
- for (auto& [_, touchState] : mTouchStatesByDisplay) {
+ for (auto& [_, touchState] : mTouchStates.mTouchStatesByDisplay) {
touchState.removeAllPointersForDevice(entry.deviceId);
}
return true;
@@ -2073,7 +2080,16 @@
}
Result<std::vector<InputTarget>, InputEventInjectionResult> result =
- findTouchedWindowTargetsLocked(currentTime, *entry);
+ mTouchStates
+ .findTouchedWindowTargets(currentTime, *entry, mConnectionManager,
+ mWindowInfos,
+ mDragState ? mDragState->dragWindow : nullptr,
+ std::bind_front(&InputDispatcher::
+ addDragEventLocked,
+ this),
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this));
if (result.ok()) {
inputTargets = std::move(*result);
@@ -2318,7 +2334,8 @@
}
// Drop key events if requested by input feature
- if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
+ if (focusedWindowHandle != nullptr &&
+ shouldDropInput(entry, focusedWindowHandle, mWindowInfos)) {
return injectionError(InputEventInjectionResult::FAILED);
}
@@ -2387,8 +2404,12 @@
return focusedWindowHandle;
}
-base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
-InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
+base::Result<std::vector<InputTarget>, os::InputEventInjectionResult>
+InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
+ nsecs_t currentTime, const MotionEntry& entry, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent, std::function<void()> dump) {
ATRACE_CALL();
std::vector<InputTarget> targets;
@@ -2448,10 +2469,12 @@
// be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
const bool isStylus = isPointerFromStylus(entry, pointerIndex);
sp<WindowInfoHandle> newTouchedWindowHandle =
- mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
+ windowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
if (isDown) {
- targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
+ targets += DispatcherTouchState::findOutsideTargets(displayId, newTouchedWindowHandle,
+ pointer.id, connections,
+ windowInfos, dump);
}
LOG_IF(INFO, newTouchedWindowHandle == nullptr)
<< "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y)
@@ -2464,8 +2487,8 @@
}
std::vector<sp<WindowInfoHandle>> newTouchedWindows =
- mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId,
- mTouchStatesByDisplay);
+ windowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId,
+ mTouchStatesByDisplay);
if (newTouchedWindowHandle != nullptr) {
// Process the foreground window first so that it is the first to receive the event.
newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle);
@@ -2478,7 +2501,8 @@
}
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
- if (!canWindowReceiveMotionLocked(windowHandle, entry)) {
+ if (!canWindowReceiveMotion(windowHandle, entry, connections, windowInfos,
+ mTouchStatesByDisplay)) {
continue;
}
@@ -2489,21 +2513,9 @@
}
// Set target flags.
- ftl::Flags<InputTarget::Flags> targetFlags;
-
- if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
- // There should only be one touched window that can be "foreground" for the pointer.
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
-
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (mWindowInfos.isWindowObscuredAtPoint(windowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (mWindowInfos.isWindowObscured(windowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ DispatcherTouchState::getTargetFlags(windowHandle, {x, y}, isSplit,
+ windowInfos);
// Update the temporary touch state.
@@ -2521,7 +2533,7 @@
if (!addResult.ok()) {
LOG(ERROR) << "Error while processing " << entry << " for "
<< windowHandle->getName();
- logDispatchStateLocked();
+ dump();
}
// If this is the pointer going down and the touched window has a wallpaper
// then also add the touched wallpaper windows so they are locked in for the
@@ -2533,7 +2545,7 @@
windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
sp<WindowInfoHandle> wallpaper =
- mWindowInfos.findWallpaperWindowBelow(windowHandle);
+ windowInfos.findWallpaperWindowBelow(windowHandle);
if (wallpaper != nullptr) {
ftl::Flags<InputTarget::Flags> wallpaperFlags =
InputTarget::Flags::WINDOW_IS_OBSCURED |
@@ -2592,7 +2604,7 @@
tempTouchState.removeHoveringPointer(entry.deviceId, pointerId);
}
- addDragEventLocked(entry);
+ addDragEvent(entry);
// Check whether touches should slip outside of the current foreground window.
if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 &&
@@ -2603,7 +2615,7 @@
tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
sp<WindowInfoHandle> newTouchedWindowHandle =
- mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
+ windowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
@@ -2613,7 +2625,8 @@
// Do not slide events to the window which can not receive motion event
if (newTouchedWindowHandle != nullptr &&
- !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) {
+ !canWindowReceiveMotion(newTouchedWindowHandle, entry, connections, windowInfos,
+ mTouchStatesByDisplay)) {
newTouchedWindowHandle = nullptr;
}
@@ -2630,26 +2643,18 @@
const TouchedWindow& touchedWindow =
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
- addPointerWindowTargetLocked(oldTouchedWindowHandle,
- InputTarget::DispatchMode::SLIPPERY_EXIT,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(oldTouchedWindowHandle,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ connections, windowInfos, dump, targets);
// Make a slippery entrance into the new window.
- ftl::Flags<InputTarget::Flags> targetFlags;
- if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (mWindowInfos.isWindowObscuredAtPoint(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (mWindowInfos.isWindowObscured(newTouchedWindowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ DispatcherTouchState::getTargetFlags(newTouchedWindowHandle, {x, y},
+ isSplit, windowInfos);
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
InputTarget::DispatchMode::SLIPPERY_ENTER,
@@ -2657,8 +2662,10 @@
entry.eventTime);
// Check if the wallpaper window should deliver the corresponding event.
- slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
- tempTouchState, entry, targets);
+ DispatcherTouchState::slipWallpaperTouch(targetFlags, oldTouchedWindowHandle,
+ newTouchedWindowHandle, tempTouchState,
+ entry, targets, connections, windowInfos,
+ dump);
tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
oldTouchedWindowHandle);
}
@@ -2671,7 +2678,7 @@
std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]};
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
// Ignore drag window for it should just track one pointer.
- if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
+ if (dragWindow == touchedWindow.windowHandle) {
continue;
}
if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
@@ -2685,17 +2692,17 @@
// Update dispatching for hover enter and exit.
{
std::vector<TouchedWindow> hoveringWindows =
- getHoveringWindowsLocked(oldState, tempTouchState, entry,
- std::bind_front(&InputDispatcher::logDispatchStateLocked,
- this));
+ getHoveringWindowsLocked(oldState, tempTouchState, entry, dump);
// Hardcode to single hovering pointer for now.
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(entry.pointerProperties[0].id);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
+ touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, pointerIds,
+ touchedWindow.getDownTimeInTarget(
+ entry.deviceId),
+ connections, windowInfos, dump, targets);
}
}
@@ -2724,7 +2731,7 @@
for (InputTarget& target : targets) {
if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
sp<WindowInfoHandle> targetWindow =
- mWindowInfos.findWindowHandle(target.connection->getToken());
+ windowInfos.findWindowHandle(target.connection->getToken());
if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
target.flags |= InputTarget::Flags::ZERO_COORDS;
}
@@ -2748,9 +2755,13 @@
if (touchingPointers.empty()) {
continue;
}
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, getPointerIds(touchingPointers),
- touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
+ DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
+ touchedWindow.dispatchMode,
+ touchedWindow.targetFlags,
+ getPointerIds(touchingPointers),
+ touchedWindow.getDownTimeInTarget(
+ entry.deviceId),
+ connections, windowInfos, dump, targets);
}
// During targeted injection, only allow owned targets to receive events
@@ -2953,11 +2964,12 @@
}
}
-void InputDispatcher::addPointerWindowTargetLocked(
+void InputDispatcher::DispatcherTouchState::addPointerWindowTarget(
const sp<android::gui::WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump, std::vector<InputTarget>& inputTargets) {
if (pointerIds.none()) {
for (const auto& target : inputTargets) {
LOG(INFO) << "Target: " << target;
@@ -2982,19 +2994,17 @@
it = inputTargets.end();
}
- const WindowInfo* windowInfo = windowHandle->getInfo();
+ const WindowInfo& windowInfo = *windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::shared_ptr<Connection> connection =
- mConnectionManager.getConnection(windowHandle->getToken());
+ std::shared_ptr<Connection> connection = connections.getConnection(windowInfo.token);
if (connection == nullptr) {
- ALOGW("Not creating InputTarget for %s, no input channel",
- windowHandle->getName().c_str());
+ ALOGW("Not creating InputTarget for %s, no input channel", windowInfo.name.c_str());
return;
}
inputTargets.push_back(
createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
- mWindowInfos.getRawTransform(*windowHandle->getInfo()),
+ windowInfos.getRawTransform(*windowHandle->getInfo()),
firstDownTimeInTarget));
it = inputTargets.end() - 1;
}
@@ -3007,14 +3017,14 @@
LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
<< ", it=" << *it;
}
- if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
+ if (it->globalScaleFactor != windowInfo.globalScaleFactor) {
LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
- << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
+ << ", windowInfo->globalScaleFactor=" << windowInfo.globalScaleFactor;
}
- Result<void> result = it->addPointers(pointerIds, windowInfo->transform);
+ Result<void> result = it->addPointers(pointerIds, windowInfo.transform);
if (!result.ok()) {
- logDispatchStateLocked();
+ dump();
LOG(FATAL) << result.error().message();
}
}
@@ -4069,7 +4079,7 @@
// Generate cancellations for touched windows first. This is to avoid generating cancellations
// through a non-touched window if there are more than one window for an input channel.
if (cancelPointers) {
- for (const auto& [displayId, touchState] : mTouchStatesByDisplay) {
+ for (const auto& [displayId, touchState] : mTouchStates.mTouchStatesByDisplay) {
if (options.displayId.has_value() && options.displayId != displayId) {
continue;
}
@@ -4204,9 +4214,15 @@
sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
mDragState.reset();
}
- addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- motionEntry.downTime, targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(window, InputTarget::DispatchMode::AS_IS,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ motionEntry.downTime, mConnectionManager,
+ mWindowInfos,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(fallbackTarget);
// Since we don't have a window, use the display transform as the raw transform.
@@ -4268,7 +4284,8 @@
}
const auto [_, touchedWindowState, displayId] =
- findTouchStateWindowAndDisplay(connection->getToken(), mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(connection->getToken(),
+ mTouchStates.mTouchStatesByDisplay);
if (touchedWindowState == nullptr) {
LOG(FATAL) << __func__ << ": Touch state is out of sync: No touched window for token";
}
@@ -4290,9 +4307,14 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
- targetFlags, pointerIds, motionEntry.downTime,
- targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, pointerIds, motionEntry.downTime,
+ mConnectionManager, mWindowInfos,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(connection, targetFlags);
// Since we don't have a window, use the display transform as the raw transform.
@@ -4559,8 +4581,8 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing gesture. That would allow us to
// complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
+ const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(args.displayId);
+ if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
if (touchState.hasTouchingPointers(args.deviceId) ||
touchState.hasHoveringPointers(args.deviceId)) {
@@ -4871,8 +4893,8 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing motion gesture. That
// would allow us to complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
+ const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
const TouchState& touchState = touchStateIt->second;
if (touchState.hasTouchingPointers(resolvedDeviceId) ||
touchState.hasHoveringPointers(resolvedDeviceId)) {
@@ -5266,9 +5288,11 @@
return dump;
}
-bool InputDispatcher::canWindowReceiveMotionLocked(
+bool InputDispatcher::canWindowReceiveMotion(
const sp<android::gui::WindowInfoHandle>& window,
- const android::inputdispatcher::MotionEntry& motionEntry) const {
+ const android::inputdispatcher::MotionEntry& motionEntry,
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates) {
const WindowInfo& info = *window->getInfo();
// Skip spy window targets that are not valid for targeted injection.
@@ -5287,7 +5311,7 @@
return false;
}
- std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken());
+ std::shared_ptr<Connection> connection = connections.getConnection(window->getToken());
if (connection == nullptr) {
ALOGW("Not sending touch to %s because there's no corresponding connection",
window->getName().c_str());
@@ -5302,8 +5326,8 @@
// Drop events that can't be trusted due to occlusion
const auto [x, y] = resolveTouchedPosition(motionEntry);
DispatcherWindowInfo::TouchOcclusionInfo occlusionInfo =
- mWindowInfos.computeTouchOcclusionInfo(window, x, y);
- if (!mWindowInfos.isTouchTrusted(occlusionInfo)) {
+ windowInfos.computeTouchOcclusionInfo(window, x, y);
+ if (!windowInfos.isTouchTrusted(occlusionInfo)) {
if (DEBUG_TOUCH_OCCLUSION) {
ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x, y);
for (const auto& log : occlusionInfo.debugInfo) {
@@ -5316,13 +5340,13 @@
}
// Drop touch events if requested by input feature
- if (shouldDropInput(motionEntry, window)) {
+ if (shouldDropInput(motionEntry, window, windowInfos)) {
return false;
}
// Ignore touches if stylus is down anywhere on screen
if (info.inputConfig.test(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH) &&
- isStylusActiveInDisplay(info.displayId, mTouchStatesByDisplay)) {
+ isStylusActiveInDisplay(info.displayId, touchStates)) {
LOG(INFO) << "Dropping touch from " << window->getName() << " because stylus is active";
return false;
}
@@ -5446,7 +5470,8 @@
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
+ if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
+ it != mTouchStates.mTouchStatesByDisplay.end()) {
TouchState& state = it->second;
for (size_t i = 0; i < state.windows.size();) {
TouchedWindow& touchedWindow = state.windows[i];
@@ -5487,7 +5512,8 @@
// Check if the hovering should stop because the window is no longer eligible to receive it
// (for example, if the touchable region changed)
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
+ if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
+ it != mTouchStates.mTouchStatesByDisplay.end()) {
TouchState& state = it->second;
for (TouchedWindow& touchedWindow : state.windows) {
std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
@@ -5793,7 +5819,7 @@
// Find the target touch state and touched window by fromToken.
auto [state, touchedWindow, displayId] =
- findTouchStateWindowAndDisplay(fromToken, mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(fromToken, mTouchStates.mTouchStatesByDisplay);
if (state == nullptr || touchedWindow == nullptr) {
ALOGD("Touch transfer failed because from window is not being touched.");
@@ -5885,11 +5911,10 @@
* Return null if there are no windows touched on that display, or if more than one foreground
* window is being touched.
*/
-sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindow(
- const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
- ui::LogicalDisplayId displayId) {
- const auto stateIt = touchStatesByDisplay.find(displayId);
- if (stateIt == touchStatesByDisplay.end()) {
+sp<WindowInfoHandle> InputDispatcher::DispatcherTouchState::findTouchedForegroundWindow(
+ ui::LogicalDisplayId displayId) const {
+ const auto stateIt = mTouchStatesByDisplay.find(displayId);
+ if (stateIt == mTouchStatesByDisplay.end()) {
ALOGI("No touch state on display %s", displayId.toString().c_str());
return nullptr;
}
@@ -5925,7 +5950,7 @@
return false;
}
- sp<WindowInfoHandle> from = findTouchedForegroundWindow(mTouchStatesByDisplay, displayId);
+ sp<WindowInfoHandle> from = mTouchStates.findTouchedForegroundWindow(displayId);
if (from == nullptr) {
ALOGE("Could not find a source window in %s for %p", __func__, destChannelToken.get());
return false;
@@ -5953,7 +5978,7 @@
resetNoFocusedWindowTimeoutLocked();
mAnrTracker.clear();
- mTouchStatesByDisplay.clear();
+ mTouchStates.mTouchStatesByDisplay.clear();
}
void InputDispatcher::logDispatchStateLocked() const {
@@ -6011,9 +6036,9 @@
dump += mFocusResolver.dump();
dump += dumpPointerCaptureStateLocked();
- if (!mTouchStatesByDisplay.empty()) {
+ if (!mTouchStates.mTouchStatesByDisplay.empty()) {
dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
- for (const auto& [displayId, state] : mTouchStatesByDisplay) {
+ for (const auto& [displayId, state] : mTouchStates.mTouchStatesByDisplay) {
std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
}
@@ -6222,7 +6247,7 @@
}
auto [statePtr, windowPtr, displayId] =
- findTouchStateWindowAndDisplay(token, mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(token, mTouchStates.mTouchStatesByDisplay);
if (statePtr == nullptr || windowPtr == nullptr) {
LOG(WARNING)
<< "Attempted to pilfer points from a channel without any on-going pointer streams."
@@ -7037,12 +7062,13 @@
mLooper->wake();
}
-bool InputDispatcher::shouldDropInput(
- const EventEntry& entry, const sp<android::gui::WindowInfoHandle>& windowHandle) const {
+bool InputDispatcher::shouldDropInput(const EventEntry& entry,
+ const sp<WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfos) {
if (windowHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::DROP_INPUT) ||
(windowHandle->getInfo()->inputConfig.test(
WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) &&
- mWindowInfos.isWindowObscured(windowHandle))) {
+ windowInfos.isWindowObscured(windowHandle))) {
ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on "
"display %s.",
ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(),
@@ -7067,7 +7093,7 @@
"cancel current touch", traceContext.getTracker());
synthesizeCancelationEventsForAllConnectionsLocked(options);
- mTouchStatesByDisplay.clear();
+ mTouchStates.mTouchStatesByDisplay.clear();
}
// Wake up poll loop since there might be work to do.
mLooper->wake();
@@ -7078,11 +7104,11 @@
mMonitorDispatchingTimeout = timeout;
}
-void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<WindowInfoHandle>& oldWindowHandle,
- const sp<WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const {
+void InputDispatcher::DispatcherTouchState::slipWallpaperTouch(
+ ftl::Flags<InputTarget::Flags> targetFlags, const sp<WindowInfoHandle>& oldWindowHandle,
+ const sp<WindowInfoHandle>& newWindowHandle, TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos, std::function<void()> dump) {
LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry;
const DeviceId deviceId = entry.deviceId;
const PointerProperties& pointerProperties = entry.pointerProperties[0];
@@ -7095,16 +7121,19 @@
const sp<WindowInfoHandle> oldWallpaper =
oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
- newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr;
+ newHasWallpaper ? windowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
return;
}
if (oldWallpaper != nullptr) {
const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
- addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
- oldTouchedWindow.targetFlags, getPointerIds(pointers),
- oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
+ DispatcherTouchState::addPointerWindowTarget(oldWallpaper,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ oldTouchedWindow.targetFlags,
+ getPointerIds(pointers),
+ oldTouchedWindow.getDownTimeInTarget(deviceId),
+ connections, windowInfos, dump, targets);
state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
}
@@ -7199,8 +7228,8 @@
ui::LogicalDisplayId displayId, DeviceId deviceId,
int32_t pointerId) {
std::scoped_lock _l(mLock);
- auto touchStateIt = mTouchStatesByDisplay.find(displayId);
- if (touchStateIt == mTouchStatesByDisplay.end()) {
+ auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt == mTouchStates.mTouchStatesByDisplay.end()) {
return false;
}
for (const TouchedWindow& window : touchStateIt->second.windows) {
@@ -7355,4 +7384,23 @@
mMaximumObscuringOpacityForTouch = opacity;
}
+ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetFlags(
+ const sp<WindowInfoHandle>& targetWindow, vec2 targetPosition, bool isSplit,
+ const DispatcherWindowInfo& windowInfos) {
+ ftl::Flags<InputTarget::Flags> targetFlags;
+ if (canReceiveForegroundTouches(*targetWindow->getInfo())) {
+ // There should only be one touched window that can be "foreground" for the pointer.
+ targetFlags |= InputTarget::Flags::FOREGROUND;
+ }
+ if (isSplit) {
+ targetFlags |= InputTarget::Flags::SPLIT;
+ }
+ if (windowInfos.isWindowObscuredAtPoint(targetWindow, targetPosition.x, targetPosition.y)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
+ } else if (windowInfos.isWindowObscured(targetWindow)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
+ }
+ return targetFlags;
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 415f4c8..58c8509 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -350,6 +350,67 @@
DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock);
+ class DispatcherTouchState {
+ public:
+ static void addPointerWindowTarget(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
+ ftl::Flags<InputTarget::Flags> targetFlags,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds,
+ std::optional<nsecs_t> firstDownTimeInTarget,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump,
+ std::vector<InputTarget>& inputTargets);
+
+ base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
+ findTouchedWindowTargets(nsecs_t currentTime, const MotionEntry& entry,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent,
+ std::function<void()> dump);
+
+ sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
+ ui::LogicalDisplayId displayId) const;
+
+ std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;
+
+ private:
+ static std::vector<InputTarget> findOutsideTargets(
+ ui::LogicalDisplayId displayId,
+ const sp<android::gui::WindowInfoHandle>& touchedWindow, int32_t pointerId,
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump);
+
+ /**
+ * Slip the wallpaper touch if necessary.
+ *
+ * @param targetFlags the target flags
+ * @param oldWindowHandle the old window that the touch slipped out of
+ * @param newWindowHandle the new window that the touch is slipping into
+ * @param state the current touch state. This will be updated if necessary to reflect the
+ * new windows that are receiving touch.
+ * @param deviceId the device id of the current motion being processed
+ * @param pointerProperties the pointer properties of the current motion being processed
+ * @param targets the current targets to add the walpaper ones to
+ * @param eventTime the new downTime for the wallpaper target
+ */
+ static void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
+ const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
+ const sp<android::gui::WindowInfoHandle>& newWindowHandle,
+ TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump);
+
+ static ftl::Flags<InputTarget::Flags> getTargetFlags(
+ const sp<android::gui::WindowInfoHandle>& targetWindow, vec2 targetPosition,
+ bool isSplit, const DispatcherWindowInfo& windowInfos);
+ };
+
+ DispatcherTouchState mTouchStates GUARDED_BY(mLock);
+
// With each iteration, InputDispatcher nominally processes one queued event,
// a timeout, or a response from an input consumer.
// This method should only be called on the input dispatcher's own thread.
@@ -378,14 +439,6 @@
// to transfer focus to a new application.
std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
- std::vector<InputTarget> findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const REQUIRES(mLock);
-
- static sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
- const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
- ui::LogicalDisplayId displayId);
-
status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
const HmacKeyManager mHmacKeyManager;
@@ -470,8 +523,11 @@
sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(
ui::LogicalDisplayId displayId) const REQUIRES(mLock);
- bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window,
- const MotionEntry& motionEntry) const REQUIRES(mLock);
+
+ static bool canWindowReceiveMotion(
+ const sp<android::gui::WindowInfoHandle>& window, const MotionEntry& motionEntry,
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates);
// Returns all the input targets (with their respective input channels) from the window handles
// passed as argument.
@@ -486,8 +542,6 @@
const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
- std::unordered_map<ui::LogicalDisplayId /*displayId*/, TouchState> mTouchStatesByDisplay
- GUARDED_BY(mLock);
std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);
void setFocusedApplicationLocked(
@@ -627,20 +681,12 @@
base::Result<sp<android::gui::WindowInfoHandle>, android::os::InputEventInjectionResult>
findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
nsecs_t& nextWakeupTime) REQUIRES(mLock);
- base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
- findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
- void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
- InputTarget::DispatchMode dispatchMode,
- ftl::Flags<InputTarget::Flags> targetFlags,
- std::bitset<MAX_POINTER_ID + 1> pointerIds,
- std::optional<nsecs_t> firstDownTimeInTarget,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
@@ -652,9 +698,9 @@
std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle,
const sp<android::gui::WindowInfoHandle>& windowHandle);
- bool shouldDropInput(const EventEntry& entry,
- const sp<android::gui::WindowInfoHandle>& windowHandle) const
- REQUIRES(mLock);
+ static bool shouldDropInput(const EventEntry& entry,
+ const sp<android::gui::WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfo);
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
@@ -774,24 +820,6 @@
sp<InputReporterInterface> mReporter;
- /**
- * Slip the wallpaper touch if necessary.
- *
- * @param targetFlags the target flags
- * @param oldWindowHandle the old window that the touch slipped out of
- * @param newWindowHandle the new window that the touch is slipping into
- * @param state the current touch state. This will be updated if necessary to reflect the new
- * windows that are receiving touch.
- * @param deviceId the device id of the current motion being processed
- * @param pointerProperties the pointer properties of the current motion being processed
- * @param targets the current targets to add the walpaper ones to
- * @param eventTime the new downTime for the wallpaper target
- */
- void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
- const sp<android::gui::WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const REQUIRES(mLock);
void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
ftl::Flags<InputTarget::Flags> newTargetFlags,
const sp<android::gui::WindowInfoHandle> fromWindowHandle,
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 1ca2998..1286a36 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -2617,12 +2617,17 @@
static constexpr ui::LogicalDisplayId DISPLAY_BOTTOM_ID = ui::LogicalDisplayId{40};
static constexpr ui::LogicalDisplayId DISPLAY_LEFT_ID = ui::LogicalDisplayId{50};
static constexpr ui::LogicalDisplayId DISPLAY_TOP_RIGHT_CORNER_ID = ui::LogicalDisplayId{60};
+ static constexpr ui::LogicalDisplayId DISPLAY_HIGH_DENSITY_ID = ui::LogicalDisplayId{70};
+
+ static constexpr int DENSITY_MEDIUM = 160;
+ static constexpr int DENSITY_HIGH = 320;
PointerChoreographerDisplayTopologyTestFixture() {
com::android::input::flags::connected_displays_cursor(true);
}
protected:
+ // Note: viewport size is in pixels and offsets in topology are in dp
std::vector<DisplayViewport> mViewports{
createViewport(DISPLAY_CENTER_ID, /*width*/ 100, /*height*/ 100, ui::ROTATION_0),
createViewport(DISPLAY_TOP_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_0),
@@ -2631,16 +2636,28 @@
createViewport(DISPLAY_LEFT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_270),
createViewport(DISPLAY_TOP_RIGHT_CORNER_ID, /*width*/ 90, /*height*/ 90,
ui::ROTATION_0),
+ // Create a high density display size 100x100 dp i.e. 200x200 px
+ createViewport(DISPLAY_HIGH_DENSITY_ID, /*width*/ 200, /*height*/ 200, ui::ROTATION_0),
};
- DisplayTopologyGraph mTopology{DISPLAY_CENTER_ID,
- {{DISPLAY_CENTER_ID,
- {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 10.0f},
- {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
- {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
- {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
- {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT,
- -90.0f}}}}};
+ DisplayTopologyGraph
+ mTopology{DISPLAY_CENTER_ID,
+ {{DISPLAY_CENTER_ID,
+ {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 50.0f},
+ // Place a high density display on the left of DISPLAY_TOP_ID with 25 dp
+ // gap
+ {DISPLAY_HIGH_DENSITY_ID, DisplayTopologyPosition::TOP, -75.0f},
+ {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
+ {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
+ {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT, -90.0f}}}},
+ {{DISPLAY_CENTER_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_ID, DENSITY_MEDIUM},
+ {DISPLAY_RIGHT_ID, DENSITY_MEDIUM},
+ {DISPLAY_BOTTOM_ID, DENSITY_MEDIUM},
+ {DISPLAY_LEFT_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DENSITY_MEDIUM},
+ {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}};
private:
DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
@@ -2731,7 +2748,7 @@
ToolType::FINGER, vec2(50, 50) /* initial x/y */,
vec2(25, -100) /* delta x/y */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_ID,
- vec2(50 + 25 - 10,
+ vec2(50 + 25 - 50,
90) /* Bottom edge: (source + delta - offset, height) */),
std::make_tuple("TransitionToBottomDisplay",
AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
@@ -2739,11 +2756,12 @@
vec2(25, 100) /* delta x/y */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_BOTTOM_ID,
vec2(50 + 25 - 10, 0) /* Top edge: (source + delta - offset, 0) */),
+ // move towards 25 dp gap between DISPLAY_HIGH_DENSITY_ID and DISPLAY_TOP_ID
std::make_tuple("NoTransitionAtTopOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
- vec2(5, 50) /* initial x/y */, vec2(0, -100) /* Move Up */,
+ vec2(35, 50) /* initial x/y */, vec2(0, -100) /* Move Up */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
- vec2(5, 0) /* Top edge */),
+ vec2(35, 0) /* Top edge */),
std::make_tuple("NoTransitionAtRightOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
vec2(95, 5) /* initial x/y */, vec2(100, 0) /* Move Right */,
@@ -2764,9 +2782,16 @@
std::make_tuple(
"TransitionAtTopRightCorner", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
ControllerType::MOUSE, ToolType::FINGER, vec2(95, 5) /* initial x/y */,
- vec2(10, -10) /* Move dignally to top right corner */,
+ vec2(10, -10) /* Move diagonally to top right corner */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_RIGHT_CORNER_ID,
- vec2(0, 90) /* bottom left corner */)),
+ vec2(0, 90) /* bottom left corner */),
+ std::make_tuple(
+ "TransitionToHighDpDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::MOUSE, vec2(20, 20) /* initial x/y */,
+ vec2(0, -50) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_HIGH_DENSITY_ID,
+ /* Bottom edge: ((source + delta - offset) * density, height) */
+ vec2((20 + 0 + 75) * 2, 200))),
[](const testing::TestParamInfo<PointerChoreographerDisplayTopologyTestFixtureParam>& p) {
return std::string{std::get<0>(p.param)};
});
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 8c80dd8..9ecd101 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -11,7 +11,7 @@
name: "sensorservice_flags",
package: "com.android.frameworks.sensorservice.flags",
container: "system",
- srcs: ["senserservice_flags.aconfig"],
+ srcs: ["sensorservice_flags.aconfig"],
}
cc_aconfig_library {
@@ -61,38 +61,38 @@
],
shared_libs: [
- "libcutils",
- "libhardware",
- "libhardware_legacy",
- "libutils",
- "liblog",
- "libactivitymanager_aidl",
- "libbatterystats_aidl",
- "libbinder",
- "libsensor",
- "libsensorprivacy",
- "libpermission",
- "libprotoutil",
- "libcrypto",
- "libbase",
- "libhidlbase",
- "libfmq",
- "libbinder_ndk",
- "packagemanager_aidl-cpp",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- "server_configurable_flags",
"libaconfig_storage_read_api_cc",
+ "libactivitymanager_aidl",
+ "libbase",
+ "libbatterystats_aidl",
+ "libbinder",
+ "libbinder_ndk",
+ "libcrypto",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhardware_legacy",
+ "libhidlbase",
+ "liblog",
+ "libpermission",
+ "libprotoutil",
+ "libsensor",
+ "libsensorprivacy",
+ "libutils",
+ "packagemanager_aidl-cpp",
+ "server_configurable_flags",
],
static_libs: [
- "libaidlcommonsupport",
- "android.hardware.sensors@1.0-convert",
"android.hardware.sensors-V1-convert",
"android.hardware.sensors-V3-ndk",
+ "android.hardware.sensors@1.0-convert",
+ "libaidlcommonsupport",
"sensorservice_flags_c_lib",
],
@@ -100,9 +100,9 @@
export_shared_lib_headers: [
"libactivitymanager_aidl",
+ "libpermission",
"libsensor",
"libsensorprivacy",
- "libpermission",
],
afdo: true,
@@ -120,9 +120,9 @@
srcs: ["main_sensorservice.cpp"],
shared_libs: [
- "libsensorservice",
- "libsensorprivacy",
"libbinder",
+ "libsensorprivacy",
+ "libsensorservice",
"libutils",
],
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/sensorservice_flags.aconfig
similarity index 100%
rename from services/sensorservice/senserservice_flags.aconfig
rename to services/sensorservice/sensorservice_flags.aconfig
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index fece312..008b057 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -654,7 +654,7 @@
// We try to do this by moving the deadline. Since the queue could be stuffed by more
// than one buffer, we take the last latch time as reference and give one vsync
// worth of time for the frame to be ready.
- nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
+ nsecs_t adjustedDeadline = mLastLatchTime + displayFrameRenderRate.getPeriodNsecs();
if (adjustedDeadline > mActuals.endTime) {
mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d117753..eecdd72 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2978,22 +2978,21 @@
}
int index = 0;
- std::array<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary = {0};
+ ftl::StaticVector<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary;
auto lastLayerStack = ui::INVALID_LAYER_STACK;
for (auto& [layer, layerFE] : layers) {
CompositionResult compositionResult{layerFE->stealCompositionResult()};
- if (index < compositionSummary.size()) {
- if (lastLayerStack != ui::INVALID_LAYER_STACK &&
- lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
+ if (lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
+ if (lastLayerStack != ui::INVALID_LAYER_STACK) {
// add a space to separate displays
- compositionSummary[index++] = ' ';
+ compositionSummary.push_back(' ');
}
lastLayerStack = layerFE->mSnapshot->outputFilter.layerStack;
- compositionSummary[index++] = layerFE->mSnapshot->classifyCompositionForDebug(
- layerFE->getHwcCompositionType());
- if (layerFE->mSnapshot->hasEffect()) {
- compositedWorkload |= adpf::Workload::EFFECTS;
- }
+ }
+ compositionSummary.push_back(
+ layerFE->mSnapshot->classifyCompositionForDebug(layerFE->getHwcCompositionType()));
+ if (layerFE->mSnapshot->hasEffect()) {
+ compositedWorkload |= adpf::Workload::EFFECTS;
}
if (compositionResult.lastClientCompositionFence) {
@@ -3010,7 +3009,8 @@
SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
ftl::Concat("Layers: ", layers.size(), " ",
ftl::truncated<WorkloadTracer::COMPOSITION_SUMMARY_SIZE>(
- compositionSummary.data()))
+ std::string_view(compositionSummary.begin(),
+ compositionSummary.size())))
.c_str());
mPowerAdvisor->setCompositedWorkload(compositedWorkload);
@@ -4605,27 +4605,6 @@
status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parent,
uint32_t* outTransformHint) {
- if (mNumLayers >= MAX_LAYERS) {
- static std::atomic<nsecs_t> lasttime{0};
- nsecs_t now = systemTime();
- if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
- ALOGE("AddClientLayer already dumped 10s before");
- return NO_MEMORY;
- } else {
- lasttime = now;
- }
-
- ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
- MAX_LAYERS);
- static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- ALOGE("Dumping on-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
- ALOGE("Dumping off-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
- }));
- return NO_MEMORY;
- }
-
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
@@ -5408,14 +5387,13 @@
mirrorArgs.addToRoot = true;
mirrorArgs.layerStackToMirror = layerStack;
result = createEffectLayer(mirrorArgs, &outResult.handle, &rootMirrorLayer);
+ if (result != NO_ERROR) {
+ return result;
+ }
outResult.layerId = rootMirrorLayer->sequence;
outResult.layerName = String16(rootMirrorLayer->getDebugName());
- result |= addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
- nullptr /* parent */, nullptr /* outTransformHint */);
- }
-
- if (result != NO_ERROR) {
- return result;
+ addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
+ nullptr /* parent */, nullptr /* outTransformHint */);
}
setTransactionFlags(eTransactionFlushNeeded);
@@ -5435,6 +5413,9 @@
[[fallthrough]];
case ISurfaceComposerClient::eFXSurfaceEffect: {
result = createBufferStateLayer(args, &outResult.handle, &layer);
+ if (result != NO_ERROR) {
+ return result;
+ }
std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
if (pendingBufferCounter) {
std::string counterName = layer->getPendingBufferCounterName();
@@ -5475,6 +5456,9 @@
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createBufferStateLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
@@ -5482,11 +5466,38 @@
status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createEffectLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
+status_t SurfaceFlinger::checkLayerLeaks() {
+ if (mNumLayers >= MAX_LAYERS) {
+ static std::atomic<nsecs_t> lasttime{0};
+ nsecs_t now = systemTime();
+ if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
+ ALOGE("CreateLayer already dumped 10s before");
+ return NO_MEMORY;
+ } else {
+ lasttime = now;
+ }
+
+ ALOGE("CreateLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
+ MAX_LAYERS);
+ static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ ALOGE("Dumping on-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
+ ALOGE("Dumping off-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
+ }));
+ return NO_MEMORY;
+ }
+ return NO_ERROR;
+}
+
void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer, uint32_t layerId) {
{
// Used to remove stalled transactions which uses an internal lock.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a99b39a..b3a3aad 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -845,6 +845,9 @@
status_t createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
+ // Checks if there are layer leaks before creating layer
+ status_t checkLayerLeaks();
+
status_t mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
gui::CreateSurfaceResult& outResult);