Loading services/inputflinger/dispatcher/InputDispatcher.cpp +37 −14 Original line number Diff line number Diff line Loading @@ -2034,6 +2034,36 @@ std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked( return responsiveMonitors; } /** * In general, touch should be always split between windows. Some exceptions: * 1. Don't split touch is if we have an active pointer down, and a new pointer is going down that's * from the same device, *and* the window that's receiving the current pointer does not support * split touch. * 2. Don't split mouse events */ bool InputDispatcher::shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) const { if (isFromSource(entry.source, AINPUT_SOURCE_MOUSE)) { // We should never split mouse events return false; } for (const TouchedWindow& touchedWindow : touchState.windows) { if (touchedWindow.windowHandle->getInfo()->isSpy()) { // Spy windows should not affect whether or not touch is split. continue; } if (touchedWindow.windowHandle->getInfo()->supportsSplitTouch()) { continue; } // Eventually, touchedWindow will contain the deviceId of each pointer that's currently // being sent there. For now, use deviceId from touch state. if (entry.deviceId == touchState.deviceId && !touchedWindow.pointerIds.isEmpty()) { return false; } } return true; } std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( nsecs_t currentTime, const MotionEntry& entry, bool* outConflictingPointerActions, InputEventInjectionResult& outInjectionResult) { Loading Loading @@ -2061,7 +2091,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( tempTouchState = *oldState; } bool isSplit = tempTouchState.split; bool isSplit = shouldSplitTouch(tempTouchState, entry); bool switchedDevice = tempTouchState.deviceId >= 0 && tempTouchState.displayId >= 0 && (tempTouchState.deviceId != entry.deviceId || tempTouchState.source != entry.source || tempTouchState.displayId != displayId); Loading Loading @@ -2141,7 +2171,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // No window is touched, so set split to true. This will allow the next pointer down to // be delivered to a new window which supports split touch. Pointers from a mouse device // should never be split. tempTouchState.split = isSplit = !isFromMouse; isSplit = !isFromMouse; } // Update hover state. Loading Loading @@ -5301,9 +5331,9 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(INDENT "TouchStatesByDisplay:\n"); for (const std::pair<int32_t, TouchState>& pair : mTouchStatesByDisplay) { const TouchState& state = pair.second; dump += StringPrintf(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n", state.displayId, toString(state.down), toString(state.split), state.deviceId, state.source); dump += StringPrintf(INDENT2 "%d: down=%s, deviceId=%d, source=0x%08x\n", state.displayId, toString(state.down), state.deviceId, state.source); if (!state.windows.empty()) { dump += INDENT3 "Windows:\n"; for (size_t i = 0; i < state.windows.size(); i++) { Loading Loading @@ -5676,10 +5706,7 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { "input channel stole pointer stream"); options.deviceId = state.deviceId; options.displayId = state.displayId; if (state.split) { // If split pointers then selectively cancel pointers otherwise cancel all pointers options.pointerIds = window.pointerIds; } std::string canceledWindows; for (const TouchedWindow& w : state.windows) { const std::shared_ptr<InputChannel> channel = Loading @@ -5698,11 +5725,7 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { // This only blocks relevant pointers to be sent to other windows window.isPilferingPointers = true; if (state.split) { state.cancelPointersForWindowsExcept(window.pointerIds, token); } else { state.filterWindowsExcept(token); } return OK; } Loading services/inputflinger/dispatcher/InputDispatcher.h +1 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,7 @@ private: // shade is pulled down while we are counting down the timeout). void resetNoFocusedWindowTimeoutLocked() REQUIRES(mLock); bool shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) const; int32_t getTargetDisplayId(const EventEntry& entry); sp<android::gui::WindowInfoHandle> findFocusedWindowTargetLocked( nsecs_t currentTime, const EventEntry& entry, nsecs_t* nextWakeupTime, Loading services/inputflinger/dispatcher/TouchState.cpp +0 −9 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ void TouchState::reset() { void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime) { if (targetFlags & InputTarget::FLAG_SPLIT) { split = true; } for (size_t i = 0; i < windows.size(); i++) { TouchedWindow& touchedWindow = windows[i]; if (touchedWindow.windowHandle == windowHandle) { Loading Loading @@ -105,11 +101,6 @@ void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); }); } void TouchState::filterWindowsExcept(const sp<IBinder>& token) { std::erase_if(windows, [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; }); } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { for (size_t i = 0; i < windows.size(); i++) { const TouchedWindow& window = windows[i]; Loading services/inputflinger/dispatcher/TouchState.h +0 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ namespace inputdispatcher { struct TouchState { bool down = false; bool split = false; // id of the device that is currently down, others are rejected int32_t deviceId = -1; Loading @@ -50,7 +49,6 @@ struct TouchState { std::optional<nsecs_t> eventTime = std::nullopt); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); void filterWindowsExcept(const sp<IBinder>& token); // Cancel pointers for current set of windows except the window with particular binder token. void cancelPointersForWindowsExcept(const BitSet32 pointerIds, const sp<IBinder>& token); Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +37 −14 Original line number Diff line number Diff line Loading @@ -2034,6 +2034,36 @@ std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked( return responsiveMonitors; } /** * In general, touch should be always split between windows. Some exceptions: * 1. Don't split touch is if we have an active pointer down, and a new pointer is going down that's * from the same device, *and* the window that's receiving the current pointer does not support * split touch. * 2. Don't split mouse events */ bool InputDispatcher::shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) const { if (isFromSource(entry.source, AINPUT_SOURCE_MOUSE)) { // We should never split mouse events return false; } for (const TouchedWindow& touchedWindow : touchState.windows) { if (touchedWindow.windowHandle->getInfo()->isSpy()) { // Spy windows should not affect whether or not touch is split. continue; } if (touchedWindow.windowHandle->getInfo()->supportsSplitTouch()) { continue; } // Eventually, touchedWindow will contain the deviceId of each pointer that's currently // being sent there. For now, use deviceId from touch state. if (entry.deviceId == touchState.deviceId && !touchedWindow.pointerIds.isEmpty()) { return false; } } return true; } std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( nsecs_t currentTime, const MotionEntry& entry, bool* outConflictingPointerActions, InputEventInjectionResult& outInjectionResult) { Loading Loading @@ -2061,7 +2091,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( tempTouchState = *oldState; } bool isSplit = tempTouchState.split; bool isSplit = shouldSplitTouch(tempTouchState, entry); bool switchedDevice = tempTouchState.deviceId >= 0 && tempTouchState.displayId >= 0 && (tempTouchState.deviceId != entry.deviceId || tempTouchState.source != entry.source || tempTouchState.displayId != displayId); Loading Loading @@ -2141,7 +2171,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // No window is touched, so set split to true. This will allow the next pointer down to // be delivered to a new window which supports split touch. Pointers from a mouse device // should never be split. tempTouchState.split = isSplit = !isFromMouse; isSplit = !isFromMouse; } // Update hover state. Loading Loading @@ -5301,9 +5331,9 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += StringPrintf(INDENT "TouchStatesByDisplay:\n"); for (const std::pair<int32_t, TouchState>& pair : mTouchStatesByDisplay) { const TouchState& state = pair.second; dump += StringPrintf(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n", state.displayId, toString(state.down), toString(state.split), state.deviceId, state.source); dump += StringPrintf(INDENT2 "%d: down=%s, deviceId=%d, source=0x%08x\n", state.displayId, toString(state.down), state.deviceId, state.source); if (!state.windows.empty()) { dump += INDENT3 "Windows:\n"; for (size_t i = 0; i < state.windows.size(); i++) { Loading Loading @@ -5676,10 +5706,7 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { "input channel stole pointer stream"); options.deviceId = state.deviceId; options.displayId = state.displayId; if (state.split) { // If split pointers then selectively cancel pointers otherwise cancel all pointers options.pointerIds = window.pointerIds; } std::string canceledWindows; for (const TouchedWindow& w : state.windows) { const std::shared_ptr<InputChannel> channel = Loading @@ -5698,11 +5725,7 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { // This only blocks relevant pointers to be sent to other windows window.isPilferingPointers = true; if (state.split) { state.cancelPointersForWindowsExcept(window.pointerIds, token); } else { state.filterWindowsExcept(token); } return OK; } Loading
services/inputflinger/dispatcher/InputDispatcher.h +1 −0 Original line number Diff line number Diff line Loading @@ -541,6 +541,7 @@ private: // shade is pulled down while we are counting down the timeout). void resetNoFocusedWindowTimeoutLocked() REQUIRES(mLock); bool shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) const; int32_t getTargetDisplayId(const EventEntry& entry); sp<android::gui::WindowInfoHandle> findFocusedWindowTargetLocked( nsecs_t currentTime, const EventEntry& entry, nsecs_t* nextWakeupTime, Loading
services/inputflinger/dispatcher/TouchState.cpp +0 −9 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ void TouchState::reset() { void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime) { if (targetFlags & InputTarget::FLAG_SPLIT) { split = true; } for (size_t i = 0; i < windows.size(); i++) { TouchedWindow& touchedWindow = windows[i]; if (touchedWindow.windowHandle == windowHandle) { Loading Loading @@ -105,11 +101,6 @@ void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); }); } void TouchState::filterWindowsExcept(const sp<IBinder>& token) { std::erase_if(windows, [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; }); } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { for (size_t i = 0; i < windows.size(); i++) { const TouchedWindow& window = windows[i]; Loading
services/inputflinger/dispatcher/TouchState.h +0 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ namespace inputdispatcher { struct TouchState { bool down = false; bool split = false; // id of the device that is currently down, others are rejected int32_t deviceId = -1; Loading @@ -50,7 +49,6 @@ struct TouchState { std::optional<nsecs_t> eventTime = std::nullopt); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); void filterWindowsExcept(const sp<IBinder>& token); // Cancel pointers for current set of windows except the window with particular binder token. void cancelPointersForWindowsExcept(const BitSet32 pointerIds, const sp<IBinder>& token); Loading