Skip to content

Commit 8d90063

Browse files
Arpit SinghAndroid (Google) Code Review
authored andcommitted
Merge changes Ibdd09f42,I624700a7 into main
* changes: [15/n Dispatcher refactor] Remove TouchState from setInputWindows [14/n Dispatcher refactor] Move TouchState methods
2 parents d6a93e9 + 24a00a9 commit 8d90063

3 files changed

Lines changed: 226 additions & 135 deletions

File tree

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 163 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,14 +1267,9 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t& nextWakeupTime) {
12671267
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
12681268
// The event is stale. However, only drop stale events if there isn't an ongoing
12691269
// gesture. That would allow us to complete the processing of the current stroke.
1270-
const auto touchStateIt =
1271-
mTouchStates.mTouchStatesByDisplay.find(motionEntry->displayId);
1272-
if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
1273-
const TouchState& touchState = touchStateIt->second;
1274-
if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
1275-
!touchState.hasHoveringPointers(motionEntry->deviceId)) {
1276-
dropReason = DropReason::STALE;
1277-
}
1270+
if (!mTouchStates.hasTouchingOrHoveringPointers(motionEntry->displayId,
1271+
motionEntry->deviceId)) {
1272+
dropReason = DropReason::STALE;
12781273
}
12791274
}
12801275
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
@@ -1716,9 +1711,7 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
17161711
synthesizeCancelationEventsForAllConnectionsLocked(options);
17171712

17181713
// Remove all active pointers from this device
1719-
for (auto& [_, touchState] : mTouchStates.mTouchStatesByDisplay) {
1720-
touchState.removeAllPointersForDevice(entry.deviceId);
1721-
}
1714+
mTouchStates.removeAllPointersForDevice(entry.deviceId);
17221715
return true;
17231716
}
17241717

@@ -4581,13 +4574,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
45814574
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
45824575
// Set the flag anyway if we already have an ongoing gesture. That would allow us to
45834576
// complete the processing of the current stroke.
4584-
const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(args.displayId);
4585-
if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
4586-
const TouchState& touchState = touchStateIt->second;
4587-
if (touchState.hasTouchingPointers(args.deviceId) ||
4588-
touchState.hasHoveringPointers(args.deviceId)) {
4589-
policyFlags |= POLICY_FLAG_PASS_TO_USER;
4590-
}
4577+
if (mTouchStates.hasTouchingOrHoveringPointers(args.displayId, args.deviceId)) {
4578+
policyFlags |= POLICY_FLAG_PASS_TO_USER;
45914579
}
45924580
}
45934581

@@ -4893,13 +4881,8 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev
48934881
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
48944882
// Set the flag anyway if we already have an ongoing motion gesture. That
48954883
// would allow us to complete the processing of the current stroke.
4896-
const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
4897-
if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
4898-
const TouchState& touchState = touchStateIt->second;
4899-
if (touchState.hasTouchingPointers(resolvedDeviceId) ||
4900-
touchState.hasHoveringPointers(resolvedDeviceId)) {
4901-
policyFlags |= POLICY_FLAG_PASS_TO_USER;
4902-
}
4884+
if (mTouchStates.hasTouchingOrHoveringPointers(displayId, resolvedDeviceId)) {
4885+
policyFlags |= POLICY_FLAG_PASS_TO_USER;
49034886
}
49044887
}
49054888

@@ -5470,72 +5453,38 @@ void InputDispatcher::setInputWindowsLocked(
54705453
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
54715454
}
54725455

5473-
if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
5474-
it != mTouchStates.mTouchStatesByDisplay.end()) {
5475-
TouchState& state = it->second;
5476-
for (size_t i = 0; i < state.windows.size();) {
5477-
TouchedWindow& touchedWindow = state.windows[i];
5478-
if (mWindowInfos.isWindowPresent(touchedWindow.windowHandle)) {
5479-
i++;
5480-
continue;
5481-
}
5482-
LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
5483-
<< " in display %" << displayId;
5484-
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5485-
"touched window was removed", traceContext.getTracker());
5486-
synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
5487-
// Since we are about to drop the touch, cancel the events for the wallpaper as
5488-
// well.
5489-
if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
5490-
touchedWindow.windowHandle->getInfo()->inputConfig.test(
5491-
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
5492-
for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
5493-
if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
5494-
options.deviceId = deviceId;
5495-
synthesizeCancelationEventsForWindowLocked(ww, options);
5496-
}
5497-
}
5498-
}
5499-
state.windows.erase(state.windows.begin() + i);
5500-
}
5501-
5502-
// If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
5503-
// could just clear the state here.
5504-
if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
5505-
std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
5506-
windowHandles.end()) {
5507-
ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
5508-
sendDropWindowCommandLocked(nullptr, 0, 0);
5509-
mDragState.reset();
5456+
CancelationOptions pointerCancellationOptions(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5457+
"touched window was removed",
5458+
traceContext.getTracker());
5459+
CancelationOptions hoverCancellationOptions(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
5460+
"WindowInfo changed", traceContext.getTracker());
5461+
const std::list<DispatcherTouchState::CancellationArgs> cancellations =
5462+
mTouchStates.updateFromWindowInfo(displayId, mWindowInfos);
5463+
for (const auto& cancellationArgs : cancellations) {
5464+
switch (cancellationArgs.mode) {
5465+
case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
5466+
pointerCancellationOptions.deviceId = cancellationArgs.deviceId;
5467+
synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
5468+
pointerCancellationOptions);
5469+
break;
5470+
case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
5471+
hoverCancellationOptions.deviceId = cancellationArgs.deviceId;
5472+
synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
5473+
hoverCancellationOptions);
5474+
break;
5475+
default:
5476+
LOG_ALWAYS_FATAL("Unexpected cancellation Mode");
55105477
}
55115478
}
55125479

5513-
// Check if the hovering should stop because the window is no longer eligible to receive it
5514-
// (for example, if the touchable region changed)
5515-
if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
5516-
it != mTouchStates.mTouchStatesByDisplay.end()) {
5517-
TouchState& state = it->second;
5518-
for (TouchedWindow& touchedWindow : state.windows) {
5519-
std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
5520-
[this, displayId, &touchedWindow](const PointerProperties& properties, float x,
5521-
float y) REQUIRES(mLock) {
5522-
const bool isStylus = properties.toolType == ToolType::STYLUS;
5523-
const ui::Transform displayTransform =
5524-
mWindowInfos.getDisplayTransform(displayId);
5525-
const bool stillAcceptsTouch =
5526-
windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(),
5527-
displayId, x, y, isStylus, displayTransform);
5528-
return !stillAcceptsTouch;
5529-
});
5530-
5531-
for (DeviceId deviceId : erasedDevices) {
5532-
CancelationOptions options(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
5533-
"WindowInfo changed",
5534-
traceContext.getTracker());
5535-
options.deviceId = deviceId;
5536-
synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
5537-
}
5538-
}
5480+
// If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
5481+
// could just clear the state here.
5482+
if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
5483+
std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
5484+
windowHandles.end()) {
5485+
ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
5486+
sendDropWindowCommandLocked(nullptr, 0, 0);
5487+
mDragState.reset();
55395488
}
55405489

55415490
// Release information for windows that are no longer present.
@@ -5552,6 +5501,76 @@ void InputDispatcher::setInputWindowsLocked(
55525501
}
55535502
}
55545503

5504+
std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5505+
InputDispatcher::DispatcherTouchState::updateFromWindowInfo(
5506+
ui::LogicalDisplayId displayId, const DispatcherWindowInfo& windowInfos) {
5507+
std::list<CancellationArgs> cancellations;
5508+
if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
5509+
TouchState& state = it->second;
5510+
cancellations = eraseRemovedWindowsFromWindowInfo(state, displayId, windowInfos);
5511+
cancellations.splice(cancellations.end(),
5512+
updateHoveringStateFromWindowInfo(state, displayId, windowInfos));
5513+
}
5514+
return cancellations;
5515+
}
5516+
5517+
std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5518+
InputDispatcher::DispatcherTouchState::eraseRemovedWindowsFromWindowInfo(
5519+
TouchState& state, ui::LogicalDisplayId displayId,
5520+
const DispatcherWindowInfo& windowInfos) {
5521+
std::list<CancellationArgs> cancellations;
5522+
for (auto it = state.windows.begin(); it != state.windows.end();) {
5523+
TouchedWindow& touchedWindow = *it;
5524+
if (windowInfos.isWindowPresent(touchedWindow.windowHandle)) {
5525+
it++;
5526+
continue;
5527+
}
5528+
LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
5529+
<< " in display %" << displayId;
5530+
cancellations.emplace_back(touchedWindow.windowHandle,
5531+
CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt);
5532+
// Since we are about to drop the touch, cancel the events for the wallpaper as well.
5533+
if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
5534+
touchedWindow.windowHandle->getInfo()->inputConfig.test(
5535+
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
5536+
for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
5537+
if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
5538+
cancellations.emplace_back(ww, CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5539+
deviceId);
5540+
}
5541+
}
5542+
}
5543+
it = state.windows.erase(it);
5544+
}
5545+
return cancellations;
5546+
}
5547+
5548+
std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
5549+
InputDispatcher::DispatcherTouchState::updateHoveringStateFromWindowInfo(
5550+
TouchState& state, ui::LogicalDisplayId displayId,
5551+
const DispatcherWindowInfo& windowInfos) {
5552+
std::list<CancellationArgs> cancellations;
5553+
// Check if the hovering should stop because the window is no longer eligible to receive it
5554+
// (for example, if the touchable region changed)
5555+
ui::Transform displayTransform = windowInfos.getDisplayTransform(displayId);
5556+
for (TouchedWindow& touchedWindow : state.windows) {
5557+
std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
5558+
[&](const PointerProperties& properties, float x, float y) {
5559+
const bool isStylus = properties.toolType == ToolType::STYLUS;
5560+
const bool stillAcceptsTouch =
5561+
windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(), displayId,
5562+
x, y, isStylus, displayTransform);
5563+
return !stillAcceptsTouch;
5564+
});
5565+
5566+
for (DeviceId deviceId : erasedDevices) {
5567+
cancellations.emplace_back(touchedWindow.windowHandle,
5568+
CancelationOptions::Mode::CANCEL_HOVER_EVENTS, deviceId);
5569+
}
5570+
}
5571+
return cancellations;
5572+
}
5573+
55555574
void InputDispatcher::setFocusedApplication(
55565575
ui::LogicalDisplayId displayId,
55575576
const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
@@ -5978,7 +5997,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
59785997
resetNoFocusedWindowTimeoutLocked();
59795998

59805999
mAnrTracker.clear();
5981-
mTouchStates.mTouchStatesByDisplay.clear();
6000+
mTouchStates.clear();
59826001
}
59836002

59846003
void InputDispatcher::logDispatchStateLocked() const {
@@ -6036,15 +6055,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const {
60366055
dump += mFocusResolver.dump();
60376056
dump += dumpPointerCaptureStateLocked();
60386057

6039-
if (!mTouchStates.mTouchStatesByDisplay.empty()) {
6040-
dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
6041-
for (const auto& [displayId, state] : mTouchStates.mTouchStatesByDisplay) {
6042-
std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
6043-
dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
6044-
}
6045-
} else {
6046-
dump += INDENT "TouchStates: <no displays touched>\n";
6047-
}
6058+
dump += addLinePrefix(mTouchStates.dump(), INDENT);
60486059

60496060
if (mDragState) {
60506061
dump += StringPrintf(INDENT "DragState:\n");
@@ -7093,7 +7104,7 @@ void InputDispatcher::cancelCurrentTouch() {
70937104
"cancel current touch", traceContext.getTracker());
70947105
synthesizeCancelationEventsForAllConnectionsLocked(options);
70957106

7096-
mTouchStates.mTouchStatesByDisplay.clear();
7107+
mTouchStates.clear();
70977108
}
70987109
// Wake up poll loop since there might be work to do.
70997110
mLooper->wake();
@@ -7228,18 +7239,7 @@ bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token,
72287239
ui::LogicalDisplayId displayId, DeviceId deviceId,
72297240
int32_t pointerId) {
72307241
std::scoped_lock _l(mLock);
7231-
auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
7232-
if (touchStateIt == mTouchStates.mTouchStatesByDisplay.end()) {
7233-
return false;
7234-
}
7235-
for (const TouchedWindow& window : touchStateIt->second.windows) {
7236-
if (window.windowHandle->getToken() == token &&
7237-
(window.hasTouchingPointer(deviceId, pointerId) ||
7238-
window.hasHoveringPointer(deviceId, pointerId))) {
7239-
return true;
7240-
}
7241-
}
7242-
return false;
7242+
return mTouchStates.isPointerInWindow(token, displayId, deviceId, pointerId);
72437243
}
72447244

72457245
void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
@@ -7403,4 +7403,56 @@ ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetF
74037403
return targetFlags;
74047404
}
74057405

7406+
bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers(
7407+
ui::LogicalDisplayId displayId, int32_t deviceId) const {
7408+
const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
7409+
if (touchStateIt == mTouchStatesByDisplay.end()) {
7410+
return false;
7411+
}
7412+
return touchStateIt->second.hasTouchingPointers(deviceId) ||
7413+
touchStateIt->second.hasHoveringPointers(deviceId);
7414+
}
7415+
7416+
bool InputDispatcher::DispatcherTouchState::isPointerInWindow(const sp<android::IBinder>& token,
7417+
ui::LogicalDisplayId displayId,
7418+
android::DeviceId deviceId,
7419+
int32_t pointerId) const {
7420+
const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
7421+
if (touchStateIt == mTouchStatesByDisplay.end()) {
7422+
return false;
7423+
}
7424+
for (const TouchedWindow& window : touchStateIt->second.windows) {
7425+
if (window.windowHandle->getToken() == token &&
7426+
(window.hasTouchingPointer(deviceId, pointerId) ||
7427+
window.hasHoveringPointer(deviceId, pointerId))) {
7428+
return true;
7429+
}
7430+
}
7431+
return false;
7432+
}
7433+
7434+
std::string InputDispatcher::DispatcherTouchState::dump() const {
7435+
std::string dump;
7436+
if (!mTouchStatesByDisplay.empty()) {
7437+
dump += StringPrintf("TouchStatesByDisplay:\n");
7438+
for (const auto& [displayId, state] : mTouchStatesByDisplay) {
7439+
std::string touchStateDump = addLinePrefix(state.dump(), INDENT);
7440+
dump += INDENT + displayId.toString() + " : " + touchStateDump;
7441+
}
7442+
} else {
7443+
dump += "TouchStates: <no displays touched>\n";
7444+
}
7445+
return dump;
7446+
}
7447+
7448+
void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice(android::DeviceId deviceId) {
7449+
for (auto& [_, touchState] : mTouchStatesByDisplay) {
7450+
touchState.removeAllPointersForDevice(deviceId);
7451+
}
7452+
}
7453+
7454+
void InputDispatcher::DispatcherTouchState::clear() {
7455+
mTouchStatesByDisplay.clear();
7456+
}
7457+
74067458
} // namespace android::inputdispatcher

0 commit comments

Comments
 (0)