Skip to content

Commit c2a4d0f

Browse files
author
Arpit Singh
committed
[17/n Dispatcher refactor] Move transferTouchGesture
In this CL we move transferTouchGesture to the DispatcherTouchStates subclass. Bug: 367661487 Bug: 245989146 Test: atest inputflinger_tests Flag: EXEMPT refactor Change-Id: Ied63de32bd1ecedcfa0aeefb8970577c10bc1808
1 parent f684980 commit c2a4d0f

2 files changed

Lines changed: 128 additions & 93 deletions

File tree

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 110 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5836,52 +5836,33 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s
58365836
{ // acquire lock
58375837
std::scoped_lock _l(mLock);
58385838

5839-
// Find the target touch state and touched window by fromToken.
5840-
auto [state, touchedWindow, displayId] =
5841-
findTouchStateWindowAndDisplay(fromToken, mTouchStates.mTouchStatesByDisplay);
5839+
ScopedSyntheticEventTracer traceContext(mTracer);
5840+
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5841+
"transferring touch from this window to another window",
5842+
traceContext.getTracker());
58425843

5843-
if (state == nullptr || touchedWindow == nullptr) {
5844-
ALOGD("Touch transfer failed because from window is not being touched.");
5845-
return false;
5846-
}
5847-
std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
5848-
if (deviceIds.size() != 1) {
5849-
LOG(INFO) << "Can't transfer touch. Currently touching devices: "
5850-
<< dumpContainer(deviceIds) << " for window: " << touchedWindow->dump();
5844+
auto result = mTouchStates.transferTouchGesture(fromToken, toToken, mWindowInfos,
5845+
mConnectionManager);
5846+
if (!result.has_value()) {
58515847
return false;
58525848
}
5853-
const DeviceId deviceId = *deviceIds.begin();
58545849

5855-
const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
5856-
const sp<WindowInfoHandle> toWindowHandle =
5857-
mWindowInfos.findWindowHandle(toToken, displayId);
5858-
if (!toWindowHandle) {
5859-
ALOGW("Cannot transfer touch because the transfer target window was not found.");
5860-
return false;
5861-
}
5850+
const auto [toWindowHandle, deviceId, pointers, cancellations, pointerDowns] =
5851+
result.value();
58625852

5863-
if (DEBUG_FOCUS) {
5864-
ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
5865-
touchedWindow->windowHandle->getName().c_str(),
5866-
toWindowHandle->getName().c_str());
5853+
for (const auto& cancellationArgs : cancellations) {
5854+
LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
5855+
CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
5856+
LOG_ALWAYS_FATAL_IF(cancellationArgs.deviceId.has_value());
5857+
synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
58675858
}
58685859

5869-
// Erase old window.
5870-
ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
5871-
std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers(deviceId);
5872-
state->removeWindowByToken(fromToken);
5873-
5874-
// Add new window.
5875-
nsecs_t downTimeInTarget = now();
5876-
ftl::Flags<InputTarget::Flags> newTargetFlags =
5877-
oldTargetFlags & (InputTarget::Flags::SPLIT);
5878-
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
5879-
newTargetFlags |= InputTarget::Flags::FOREGROUND;
5860+
for (const auto& pointerDownArgs : pointerDowns) {
5861+
synthesizePointerDownEventsForConnectionLocked(pointerDownArgs.downTimeInTarget,
5862+
pointerDownArgs.connection,
5863+
pointerDownArgs.targetFlags,
5864+
traceContext.getTracker());
58805865
}
5881-
// Transferring touch focus using this API should not effect the focused window.
5882-
newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5883-
state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5884-
deviceId, pointers, downTimeInTarget);
58855866

58865867
// Store the dragging window.
58875868
if (isDragDrop) {
@@ -5894,53 +5875,92 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s
58945875
const size_t id = pointers.begin()->id;
58955876
mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id);
58965877
}
5897-
5898-
// Synthesize cancel for old window and down for new window.
5899-
ScopedSyntheticEventTracer traceContext(mTracer);
5900-
std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
5901-
std::shared_ptr<Connection> toConnection = mConnectionManager.getConnection(toToken);
5902-
if (fromConnection != nullptr && toConnection != nullptr) {
5903-
fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
5904-
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5905-
"transferring touch from this window to another window",
5906-
traceContext.getTracker());
5907-
synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
5908-
5909-
// Check if the wallpaper window should deliver the corresponding event.
5910-
const auto [cancellations, pointerDowns] =
5911-
mTouchStates.transferWallpaperTouch(fromWindowHandle, toWindowHandle, displayId,
5912-
deviceId, pointers, oldTargetFlags,
5913-
newTargetFlags, mWindowInfos,
5914-
mConnectionManager);
5915-
for (const auto& cancellationArgs : cancellations) {
5916-
// touch should be cancelled for old wallpaper window
5917-
LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
5918-
CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
5919-
synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
5920-
}
5921-
for (const auto& pointerDownArgs : pointerDowns) {
5922-
// expect pointer down on new the wallpaper window
5923-
synthesizePointerDownEventsForConnectionLocked(pointerDownArgs.downTimeInTarget,
5924-
pointerDownArgs.connection,
5925-
pointerDownArgs.targetFlags,
5926-
traceContext.getTracker());
5927-
}
5928-
5929-
// Because new window may have a wallpaper window, it will merge input state from it
5930-
// parent window, after this the firstNewPointerIdx in input state will be reset, then
5931-
// it will cause new move event be thought inconsistent, so we should synthesize the
5932-
// down event after it reset.
5933-
synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
5934-
newTargetFlags,
5935-
traceContext.getTracker());
5936-
}
59375878
} // release lock
59385879

59395880
// Wake up poll loop since it may need to make new input dispatching choices.
59405881
mLooper->wake();
59415882
return true;
59425883
}
59435884

5885+
std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
5886+
std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
5887+
std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>>
5888+
InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken,
5889+
const sp<android::IBinder>& toToken,
5890+
const DispatcherWindowInfo& windowInfos,
5891+
const ConnectionManager& connections) {
5892+
// Find the target touch state and touched window by fromToken.
5893+
auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken);
5894+
if (!touchStateWindowAndDisplay.has_value()) {
5895+
ALOGD("Touch transfer failed because from window is not being touched.");
5896+
return std::nullopt;
5897+
}
5898+
5899+
auto [state, touchedWindow, displayId] = touchStateWindowAndDisplay.value();
5900+
std::set<DeviceId> deviceIds = touchedWindow.getTouchingDeviceIds();
5901+
if (deviceIds.size() != 1) {
5902+
LOG(INFO) << "Can't transfer touch. Currently touching devices: "
5903+
<< dumpContainer(deviceIds) << " for window: " << touchedWindow.dump();
5904+
return std::nullopt;
5905+
}
5906+
const DeviceId deviceId = *deviceIds.begin();
5907+
5908+
const sp<WindowInfoHandle> fromWindowHandle = touchedWindow.windowHandle;
5909+
const sp<WindowInfoHandle> toWindowHandle = windowInfos.findWindowHandle(toToken, displayId);
5910+
if (!toWindowHandle) {
5911+
ALOGW("Cannot transfer touch because the transfer target window was not found.");
5912+
return std::nullopt;
5913+
}
5914+
5915+
if (DEBUG_FOCUS) {
5916+
ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
5917+
fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
5918+
}
5919+
5920+
// Erase old window.
5921+
ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow.targetFlags;
5922+
std::vector<PointerProperties> pointers = touchedWindow.getTouchingPointers(deviceId);
5923+
state.removeWindowByToken(fromToken);
5924+
5925+
// Add new window.
5926+
nsecs_t downTimeInTarget = now();
5927+
ftl::Flags<InputTarget::Flags> newTargetFlags = oldTargetFlags & (InputTarget::Flags::SPLIT);
5928+
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
5929+
newTargetFlags |= InputTarget::Flags::FOREGROUND;
5930+
}
5931+
// Transferring touch focus using this API should not effect the focused window.
5932+
newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5933+
state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5934+
deviceId, pointers, downTimeInTarget);
5935+
5936+
// Synthesize cancel for old window and down for new window.
5937+
std::shared_ptr<Connection> fromConnection = connections.getConnection(fromToken);
5938+
std::shared_ptr<Connection> toConnection = connections.getConnection(toToken);
5939+
std::list<CancellationArgs> cancellations;
5940+
std::list<PointerDownArgs> pointerDowns;
5941+
if (fromConnection != nullptr && toConnection != nullptr) {
5942+
fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
5943+
cancellations.emplace_back(fromWindowHandle,
5944+
CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt);
5945+
5946+
// Check if the wallpaper window should deliver the corresponding event.
5947+
auto [wallpaperCancellations, wallpaperPointerDowns] =
5948+
transferWallpaperTouch(fromWindowHandle, toWindowHandle, state, deviceId, pointers,
5949+
oldTargetFlags, newTargetFlags, windowInfos, connections);
5950+
5951+
cancellations.splice(cancellations.end(), wallpaperCancellations);
5952+
pointerDowns.splice(pointerDowns.end(), wallpaperPointerDowns);
5953+
5954+
// Because new window may have a wallpaper window, it will merge input state from it
5955+
// parent window, after this the firstNewPointerIdx in input state will be reset, then
5956+
// it will cause new move event be thought inconsistent, so we should synthesize the
5957+
// down event after it reset.
5958+
pointerDowns.emplace_back(downTimeInTarget, toConnection, newTargetFlags);
5959+
}
5960+
5961+
return std::make_tuple(toWindowHandle, deviceId, pointers, cancellations, pointerDowns);
5962+
}
5963+
59445964
/**
59455965
* Get the touched foreground window on the given display.
59465966
* Return null if there are no windows touched on that display, or if more than one foreground
@@ -7176,13 +7196,11 @@ std::pair<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
71767196
std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>
71777197
InputDispatcher::DispatcherTouchState::transferWallpaperTouch(
71787198
const sp<gui::WindowInfoHandle> fromWindowHandle,
7179-
const sp<gui::WindowInfoHandle> toWindowHandle, ui::LogicalDisplayId displayId,
7199+
const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
71807200
android::DeviceId deviceId, const std::vector<PointerProperties>& pointers,
71817201
ftl::Flags<InputTarget::Flags> oldTargetFlags,
71827202
ftl::Flags<InputTarget::Flags> newTargetFlags, const DispatcherWindowInfo& windowInfos,
71837203
const ConnectionManager& connections) {
7184-
TouchState& state = getTouchState(displayId);
7185-
71867204
const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
71877205
fromWindowHandle->getInfo()->inputConfig.test(
71887206
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -7478,10 +7496,17 @@ void InputDispatcher::DispatcherTouchState::clear() {
74787496
mTouchStatesByDisplay.clear();
74797497
}
74807498

7481-
TouchState& InputDispatcher::DispatcherTouchState::getTouchState(ui::LogicalDisplayId displayId) {
7482-
auto touchStateIt = mTouchStatesByDisplay.find(displayId);
7483-
LOG_ALWAYS_FATAL_IF(touchStateIt == mTouchStatesByDisplay.end());
7484-
return touchStateIt->second;
7499+
std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
7500+
InputDispatcher::DispatcherTouchState::findTouchStateWindowAndDisplay(
7501+
const sp<android::IBinder>& token) {
7502+
for (auto& [displayId, state] : mTouchStatesByDisplay) {
7503+
for (TouchedWindow& w : state.windows) {
7504+
if (w.windowHandle->getToken() == token) {
7505+
return std::make_tuple(std::ref(state), std::ref(w), displayId);
7506+
}
7507+
}
7508+
}
7509+
return std::nullopt;
74857510
}
74867511

74877512
} // namespace android::inputdispatcher

services/inputflinger/dispatcher/InputDispatcher.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,20 +399,30 @@ class InputDispatcher : public android::InputDispatcherInterface {
399399

400400
void removeAllPointersForDevice(DeviceId deviceId);
401401

402-
std::pair<std::list<CancellationArgs>, std::list<PointerDownArgs>> transferWallpaperTouch(
403-
const sp<gui::WindowInfoHandle> fromWindowHandle,
404-
const sp<gui::WindowInfoHandle> toWindowHandle, ui::LogicalDisplayId displayId,
405-
DeviceId deviceId, const std::vector<PointerProperties>& pointers,
406-
ftl::Flags<InputTarget::Flags> oldTargetFlags,
407-
ftl::Flags<InputTarget::Flags> newTargetFlags,
408-
const DispatcherWindowInfo& windowInfos, const ConnectionManager& connections);
402+
// transfer touch between provided tokens, returns destination WindowHandle, deviceId,
403+
// pointers, list of cancelled windows and pointers on successful transfer.
404+
std::optional<
405+
std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
406+
std::list<CancellationArgs>, std::list<PointerDownArgs>>>
407+
transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
408+
const DispatcherWindowInfo& windowInfos,
409+
const ConnectionManager& connections);
409410

410411
void clear();
411412

412413
std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;
413414

414415
private:
415-
TouchState& getTouchState(ui::LogicalDisplayId displayId);
416+
std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
417+
findTouchStateWindowAndDisplay(const sp<IBinder>& token);
418+
419+
std::pair<std::list<CancellationArgs>, std::list<PointerDownArgs>> transferWallpaperTouch(
420+
const sp<gui::WindowInfoHandle> fromWindowHandle,
421+
const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
422+
DeviceId deviceId, const std::vector<PointerProperties>& pointers,
423+
ftl::Flags<InputTarget::Flags> oldTargetFlags,
424+
ftl::Flags<InputTarget::Flags> newTargetFlags,
425+
const DispatcherWindowInfo& windowInfos, const ConnectionManager& connections);
416426

417427
static std::list<CancellationArgs> eraseRemovedWindowsFromWindowInfo(
418428
TouchState& state, ui::LogicalDisplayId displayId,

0 commit comments

Comments
 (0)