Loading services/inputflinger/dispatcher/InputDispatcher.cpp +23 −19 Original line number Original line Diff line number Diff line Loading @@ -2184,18 +2184,20 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction; const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction; const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE); const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE); if (newGesture) { // If pointers are already down, let's finish the current gesture and ignore the new events // If pointers are already down, let's finish the current gesture and ignore the new events // from another device. // from another device. However, if the new event is a down event, let's cancel the current if (switchedDevice && wasDown) { // touch and let the new one take over. ALOGI("Dropping event because a pointer for a different device is already down " if (switchedDevice && wasDown && !isDown) { "in display %" PRId32, LOG(INFO) << "Dropping event because a pointer for device " << oldState->deviceId displayId); << " is already down in display " << displayId << ": " << entry.getDescription(); // TODO(b/211379801): test multiple simultaneous input streams. // TODO(b/211379801): test multiple simultaneous input streams. outInjectionResult = InputEventInjectionResult::FAILED; outInjectionResult = InputEventInjectionResult::FAILED; return {}; // wrong device return {}; // wrong device } } tempTouchState.clearWindowsWithoutPointers(); if (newGesture) { // If a new gesture is starting, clear the touch state completely. tempTouchState.reset(); tempTouchState.deviceId = entry.deviceId; tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; tempTouchState.source = entry.source; isSplit = false; isSplit = false; Loading Loading @@ -2317,6 +2319,10 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN || const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN || maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN; maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN; // TODO(b/211379801): Currently, even if pointerIds are empty (hover case), we would // still add a window to the touch state. We should avoid doing that, but some of the // later checks ("at least one foreground window") rely on this in order to dispatch // the event properly, so that needs to be updated, possibly by looking at InputTargets. tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, isDownOrPointerDown isDownOrPointerDown ? std::make_optional(entry.eventTime) ? std::make_optional(entry.eventTime) Loading Loading @@ -2369,10 +2375,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( // If the pointer is not currently down, then ignore the event. // If the pointer is not currently down, then ignore the event. if (!tempTouchState.isDown()) { if (!tempTouchState.isDown()) { ALOGD_IF(DEBUG_FOCUS, LOG(INFO) << "Dropping event because the pointer is not down or we previously " "Dropping event because the pointer is not down or we previously " "dropped the pointer down event in display " "dropped the pointer down event in display %" PRId32 ": %s", << displayId << ": " << entry.getDescription(); displayId, entry.getDescription().c_str()); outInjectionResult = InputEventInjectionResult::FAILED; outInjectionResult = InputEventInjectionResult::FAILED; return {}; return {}; } } Loading Loading @@ -2530,7 +2535,6 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( } } // Success! Output targets from the touch state. // Success! Output targets from the touch state. tempTouchState.clearWindowsWithoutPointers(); for (const TouchedWindow& touchedWindow : tempTouchState.windows) { for (const TouchedWindow& touchedWindow : tempTouchState.windows) { if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) { if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) { // Windows with hovering pointers are getting persisted inside TouchState. // Windows with hovering pointers are getting persisted inside TouchState. Loading Loading @@ -2570,14 +2574,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { // Pointer went up. // Pointer went up. tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.clearWindowsWithoutPointers(); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. // All pointers up or canceled. tempTouchState.reset(); tempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { // First pointer went down. // First pointer went down. if (oldState && oldState->isDown()) { if (oldState && (oldState->isDown() || oldState->hasHoveringPointers())) { ALOGD("Conflicting pointer actions: Down received while already down."); ALOGD("Conflicting pointer actions: Down received while already down or hovering."); *outConflictingPointerActions = true; *outConflictingPointerActions = true; } } } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { Loading @@ -2600,6 +2603,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( // state was only valid for this one action. // state was only valid for this one action. if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) { if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) { if (displayId >= 0) { if (displayId >= 0) { tempTouchState.clearWindowsWithoutPointers(); mTouchStatesByDisplay[displayId] = tempTouchState; mTouchStatesByDisplay[displayId] = tempTouchState; } else { } else { mTouchStatesByDisplay.erase(displayId); mTouchStatesByDisplay.erase(displayId); Loading services/inputflinger/dispatcher/TouchState.cpp +11 −5 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ void TouchState::removeTouchedPointer(int32_t pointerId) { for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.removeTouchingPointer(pointerId); touchedWindow.removeTouchingPointer(pointerId); } } clearWindowsWithoutPointers(); } } void TouchState::removeTouchedPointerFromWindow( void TouchState::removeTouchedPointerFromWindow( Loading @@ -42,6 +43,7 @@ void TouchState::removeTouchedPointerFromWindow( for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { if (touchedWindow.windowHandle == windowHandle) { if (touchedWindow.windowHandle == windowHandle) { touchedWindow.removeTouchingPointer(pointerId); touchedWindow.removeTouchingPointer(pointerId); clearWindowsWithoutPointers(); return; return; } } } } Loading @@ -51,6 +53,7 @@ void TouchState::clearHoveringPointers() { for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.clearHoveringPointers(); touchedWindow.clearHoveringPointers(); } } clearWindowsWithoutPointers(); } } void TouchState::clearWindowsWithoutPointers() { void TouchState::clearWindowsWithoutPointers() { Loading Loading @@ -135,7 +138,7 @@ void TouchState::cancelPointersForWindowsExcept(std::bitset<MAX_POINTER_ID + 1> w.pointerIds &= ~pointerIds; w.pointerIds &= ~pointerIds; } } }); }); std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.none(); }); clearWindowsWithoutPointers(); } } /** /** Loading Loading @@ -164,7 +167,7 @@ void TouchState::cancelPointersForNonPilferingWindows() { w.pilferedPointerIds ^ allPilferedPointerIds; w.pilferedPointerIds ^ allPilferedPointerIds; w.pointerIds &= ~pilferedByOtherWindows; w.pointerIds &= ~pilferedByOtherWindows; }); }); std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.none(); }); clearWindowsWithoutPointers(); } } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { Loading Loading @@ -216,6 +219,11 @@ bool TouchState::isDown() const { [](const TouchedWindow& window) { return window.pointerIds.any(); }); [](const TouchedWindow& window) { return window.pointerIds.any(); }); } } bool TouchState::hasHoveringPointers() const { return std::any_of(windows.begin(), windows.end(), [](const TouchedWindow& window) { return window.hasHoveringPointers(); }); } std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, int32_t pointerId) const { int32_t pointerId) const { std::set<sp<WindowInfoHandle>> out; std::set<sp<WindowInfoHandle>> out; Loading @@ -231,9 +239,7 @@ void TouchState::removeHoveringPointer(int32_t hoveringDeviceId, int32_t hoverin for (TouchedWindow& window : windows) { for (TouchedWindow& window : windows) { window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); } } std::erase_if(windows, [](const TouchedWindow& w) { clearWindowsWithoutPointers(); return w.pointerIds.none() && !w.hasHoveringPointers(); }); } } std::string TouchState::dump() const { std::string TouchState::dump() const { Loading services/inputflinger/dispatcher/TouchState.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -71,6 +71,7 @@ struct TouchState { const sp<android::gui::WindowInfoHandle>& windowHandle) const; const sp<android::gui::WindowInfoHandle>& windowHandle) const; // Whether any of the windows are currently being touched // Whether any of the windows are currently being touched bool isDown() const; bool isDown() const; bool hasHoveringPointers() const; std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( int32_t deviceId, int32_t pointerId) const; int32_t deviceId, int32_t pointerId) const; Loading services/inputflinger/tests/InputDispatcher_test.cpp +427 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +23 −19 Original line number Original line Diff line number Diff line Loading @@ -2184,18 +2184,20 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction; const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction; const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE); const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE); if (newGesture) { // If pointers are already down, let's finish the current gesture and ignore the new events // If pointers are already down, let's finish the current gesture and ignore the new events // from another device. // from another device. However, if the new event is a down event, let's cancel the current if (switchedDevice && wasDown) { // touch and let the new one take over. ALOGI("Dropping event because a pointer for a different device is already down " if (switchedDevice && wasDown && !isDown) { "in display %" PRId32, LOG(INFO) << "Dropping event because a pointer for device " << oldState->deviceId displayId); << " is already down in display " << displayId << ": " << entry.getDescription(); // TODO(b/211379801): test multiple simultaneous input streams. // TODO(b/211379801): test multiple simultaneous input streams. outInjectionResult = InputEventInjectionResult::FAILED; outInjectionResult = InputEventInjectionResult::FAILED; return {}; // wrong device return {}; // wrong device } } tempTouchState.clearWindowsWithoutPointers(); if (newGesture) { // If a new gesture is starting, clear the touch state completely. tempTouchState.reset(); tempTouchState.deviceId = entry.deviceId; tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; tempTouchState.source = entry.source; isSplit = false; isSplit = false; Loading Loading @@ -2317,6 +2319,10 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN || const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN || maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN; maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN; // TODO(b/211379801): Currently, even if pointerIds are empty (hover case), we would // still add a window to the touch state. We should avoid doing that, but some of the // later checks ("at least one foreground window") rely on this in order to dispatch // the event properly, so that needs to be updated, possibly by looking at InputTargets. tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, isDownOrPointerDown isDownOrPointerDown ? std::make_optional(entry.eventTime) ? std::make_optional(entry.eventTime) Loading Loading @@ -2369,10 +2375,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( // If the pointer is not currently down, then ignore the event. // If the pointer is not currently down, then ignore the event. if (!tempTouchState.isDown()) { if (!tempTouchState.isDown()) { ALOGD_IF(DEBUG_FOCUS, LOG(INFO) << "Dropping event because the pointer is not down or we previously " "Dropping event because the pointer is not down or we previously " "dropped the pointer down event in display " "dropped the pointer down event in display %" PRId32 ": %s", << displayId << ": " << entry.getDescription(); displayId, entry.getDescription().c_str()); outInjectionResult = InputEventInjectionResult::FAILED; outInjectionResult = InputEventInjectionResult::FAILED; return {}; return {}; } } Loading Loading @@ -2530,7 +2535,6 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( } } // Success! Output targets from the touch state. // Success! Output targets from the touch state. tempTouchState.clearWindowsWithoutPointers(); for (const TouchedWindow& touchedWindow : tempTouchState.windows) { for (const TouchedWindow& touchedWindow : tempTouchState.windows) { if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) { if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) { // Windows with hovering pointers are getting persisted inside TouchState. // Windows with hovering pointers are getting persisted inside TouchState. Loading Loading @@ -2570,14 +2574,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { // Pointer went up. // Pointer went up. tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.clearWindowsWithoutPointers(); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. // All pointers up or canceled. tempTouchState.reset(); tempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { // First pointer went down. // First pointer went down. if (oldState && oldState->isDown()) { if (oldState && (oldState->isDown() || oldState->hasHoveringPointers())) { ALOGD("Conflicting pointer actions: Down received while already down."); ALOGD("Conflicting pointer actions: Down received while already down or hovering."); *outConflictingPointerActions = true; *outConflictingPointerActions = true; } } } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { Loading @@ -2600,6 +2603,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( // state was only valid for this one action. // state was only valid for this one action. if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) { if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) { if (displayId >= 0) { if (displayId >= 0) { tempTouchState.clearWindowsWithoutPointers(); mTouchStatesByDisplay[displayId] = tempTouchState; mTouchStatesByDisplay[displayId] = tempTouchState; } else { } else { mTouchStatesByDisplay.erase(displayId); mTouchStatesByDisplay.erase(displayId); Loading
services/inputflinger/dispatcher/TouchState.cpp +11 −5 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ void TouchState::removeTouchedPointer(int32_t pointerId) { for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.removeTouchingPointer(pointerId); touchedWindow.removeTouchingPointer(pointerId); } } clearWindowsWithoutPointers(); } } void TouchState::removeTouchedPointerFromWindow( void TouchState::removeTouchedPointerFromWindow( Loading @@ -42,6 +43,7 @@ void TouchState::removeTouchedPointerFromWindow( for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { if (touchedWindow.windowHandle == windowHandle) { if (touchedWindow.windowHandle == windowHandle) { touchedWindow.removeTouchingPointer(pointerId); touchedWindow.removeTouchingPointer(pointerId); clearWindowsWithoutPointers(); return; return; } } } } Loading @@ -51,6 +53,7 @@ void TouchState::clearHoveringPointers() { for (TouchedWindow& touchedWindow : windows) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.clearHoveringPointers(); touchedWindow.clearHoveringPointers(); } } clearWindowsWithoutPointers(); } } void TouchState::clearWindowsWithoutPointers() { void TouchState::clearWindowsWithoutPointers() { Loading Loading @@ -135,7 +138,7 @@ void TouchState::cancelPointersForWindowsExcept(std::bitset<MAX_POINTER_ID + 1> w.pointerIds &= ~pointerIds; w.pointerIds &= ~pointerIds; } } }); }); std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.none(); }); clearWindowsWithoutPointers(); } } /** /** Loading Loading @@ -164,7 +167,7 @@ void TouchState::cancelPointersForNonPilferingWindows() { w.pilferedPointerIds ^ allPilferedPointerIds; w.pilferedPointerIds ^ allPilferedPointerIds; w.pointerIds &= ~pilferedByOtherWindows; w.pointerIds &= ~pilferedByOtherWindows; }); }); std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.none(); }); clearWindowsWithoutPointers(); } } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { Loading Loading @@ -216,6 +219,11 @@ bool TouchState::isDown() const { [](const TouchedWindow& window) { return window.pointerIds.any(); }); [](const TouchedWindow& window) { return window.pointerIds.any(); }); } } bool TouchState::hasHoveringPointers() const { return std::any_of(windows.begin(), windows.end(), [](const TouchedWindow& window) { return window.hasHoveringPointers(); }); } std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, int32_t pointerId) const { int32_t pointerId) const { std::set<sp<WindowInfoHandle>> out; std::set<sp<WindowInfoHandle>> out; Loading @@ -231,9 +239,7 @@ void TouchState::removeHoveringPointer(int32_t hoveringDeviceId, int32_t hoverin for (TouchedWindow& window : windows) { for (TouchedWindow& window : windows) { window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); } } std::erase_if(windows, [](const TouchedWindow& w) { clearWindowsWithoutPointers(); return w.pointerIds.none() && !w.hasHoveringPointers(); }); } } std::string TouchState::dump() const { std::string TouchState::dump() const { Loading
services/inputflinger/dispatcher/TouchState.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -71,6 +71,7 @@ struct TouchState { const sp<android::gui::WindowInfoHandle>& windowHandle) const; const sp<android::gui::WindowInfoHandle>& windowHandle) const; // Whether any of the windows are currently being touched // Whether any of the windows are currently being touched bool isDown() const; bool isDown() const; bool hasHoveringPointers() const; std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( int32_t deviceId, int32_t pointerId) const; int32_t deviceId, int32_t pointerId) const; Loading
services/inputflinger/tests/InputDispatcher_test.cpp +427 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes