Loading include/input/PrintTools.h +0 −6 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <bitset> #include <map> #include <optional> #include <set> Loading @@ -24,11 +23,6 @@ namespace android { template <size_t N> std::string bitsetToString(const std::bitset<N>& bitset) { return bitset.to_string(); } template <typename T> inline std::string constToString(const T& v) { return std::to_string(v); Loading services/inputflinger/dispatcher/InputDispatcher.cpp +64 −100 Original line number Diff line number Diff line Loading @@ -554,65 +554,6 @@ std::optional<nsecs_t> getDownTime(const EventEntry& eventEntry) { return std::nullopt; } /** * Compare the old touch state to the new touch state, and generate the corresponding touched * windows (== input targets). * If a window had the hovering pointer, but now it doesn't, produce HOVER_EXIT for that window. * If the pointer just entered the new window, produce HOVER_ENTER. * For pointers remaining in the window, produce HOVER_MOVE. */ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState, const TouchState& newTouchState, const MotionEntry& entry) { std::vector<TouchedWindow> out; const int32_t maskedAction = MotionEvent::getActionMasked(entry.action); if (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER && maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE && maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) { // Not a hover event - don't need to do anything return out; } // We should consider all hovering pointers here. But for now, just use the first one const int32_t pointerId = entry.pointerProperties[0].id; std::set<sp<WindowInfoHandle>> oldWindows; if (oldState != nullptr) { oldWindows = oldState->getWindowsWithHoveringPointer(entry.deviceId, pointerId); } std::set<sp<WindowInfoHandle>> newWindows = newTouchState.getWindowsWithHoveringPointer(entry.deviceId, pointerId); // If the pointer is no longer in the new window set, send HOVER_EXIT. for (const sp<WindowInfoHandle>& oldWindow : oldWindows) { if (newWindows.find(oldWindow) == newWindows.end()) { TouchedWindow touchedWindow; touchedWindow.windowHandle = oldWindow; touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_EXIT; touchedWindow.pointerIds.markBit(pointerId); out.push_back(touchedWindow); } } for (const sp<WindowInfoHandle>& newWindow : newWindows) { TouchedWindow touchedWindow; touchedWindow.windowHandle = newWindow; if (oldWindows.find(newWindow) == oldWindows.end()) { // Any windows that have this pointer now, and didn't have it before, should get // HOVER_ENTER touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER; } else { // This pointer was already sent to the window. Use ACTION_HOVER_MOVE. LOG_ALWAYS_FATAL_IF(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE); touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS; } touchedWindow.pointerIds.markBit(pointerId); out.push_back(touchedWindow); } return out; } } // namespace // --- InputDispatcher --- Loading Loading @@ -2142,6 +2083,8 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // Update the touch state as needed based on the properties of the touch event. outInjectionResult = InputEventInjectionResult::PENDING; sp<WindowInfoHandle> newHoverWindowHandle(mLastHoverWindowHandle); sp<WindowInfoHandle> newTouchedWindowHandle; // Copy current touch state into tempTouchState. // This state will be used to update mTouchStatesByDisplay at the end of this function. Loading Loading @@ -2174,7 +2117,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( outInjectionResult = InputEventInjectionResult::FAILED; return touchedWindows; // wrong device } tempTouchState.clearWindowsWithoutPointers(); tempTouchState.reset(); tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; isSplit = false; Loading @@ -2187,21 +2130,14 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( return touchedWindows; // wrong device } if (isHoverAction) { // For hover actions, we will treat 'tempTouchState' as a new state, so let's erase // all of the existing hovering pointers and recompute. tempTouchState.clearHoveringPointers(); } if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { /* Case 1: New splittable pointer going down, or need target for hover or scroll. */ const auto [x, y] = resolveTouchedPosition(entry); const int32_t pointerIndex = getMotionEventActionPointerIndex(action); const bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN; const bool isStylus = isPointerFromStylus(entry, pointerIndex); sp<WindowInfoHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus, isDown /*addOutsideTargets*/); newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus, isDown /*addOutsideTargets*/); // Handle the case where we did not find a window. if (newTouchedWindowHandle == nullptr) { Loading Loading @@ -2236,6 +2172,15 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( isSplit = !isFromMouse; } // Update hover state. if (newTouchedWindowHandle != nullptr) { if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) { newHoverWindowHandle = nullptr; } else if (isHoverAction) { newHoverWindowHandle = newTouchedWindowHandle; } } std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus); if (newTouchedWindowHandle != nullptr) { Loading @@ -2255,18 +2200,6 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( continue; } if (isHoverAction) { const int32_t pointerId = entry.pointerProperties[0].id; if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) { // Pointer left. Remove it tempTouchState.removeHoveringPointer(entry.deviceId, pointerId); } else { // The "windowHandle" is the target of this hovering pointer. tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointerId); } } // Set target flags. ftl::Flags<InputTarget::Flags> targetFlags = InputTarget::Flags::DISPATCH_AS_IS; Loading @@ -2286,9 +2219,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // Update the temporary touch state. BitSet32 pointerIds; if (!isHoverAction) { pointerIds.markBit(entry.pointerProperties[pointerIndex].id); } tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, entry.eventTime); Loading Loading @@ -2324,7 +2255,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( const bool isStylus = isPointerFromStylus(entry, 0 /*pointerIndex*/); sp<WindowInfoHandle> oldTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle(); sp<WindowInfoHandle> newTouchedWindowHandle = newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus); // Verify targeted injection. Loading Loading @@ -2395,11 +2326,36 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } // Update dispatching for hover enter and exit. { std::vector<TouchedWindow> hoveringWindows = getHoveringWindowsLocked(oldState, tempTouchState, entry); touchedWindows.insert(touchedWindows.end(), hoveringWindows.begin(), hoveringWindows.end()); if (newHoverWindowHandle != mLastHoverWindowHandle) { // Let the previous window know that the hover sequence is over, unless we already did // it when dispatching it as is to newTouchedWindowHandle. if (mLastHoverWindowHandle != nullptr && (maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT || mLastHoverWindowHandle != newTouchedWindowHandle)) { if (DEBUG_HOVER) { ALOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, InputTarget::Flags::DISPATCH_AS_HOVER_EXIT, BitSet32(0)); } // Let the new window know that the hover sequence is starting, unless we already did it // when dispatching it as is to newTouchedWindowHandle. if (newHoverWindowHandle != nullptr && (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER || newHoverWindowHandle != newTouchedWindowHandle)) { if (DEBUG_HOVER) { ALOGD("Sending hover enter event to window %s.", newHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(newHoverWindowHandle, InputTarget::Flags::DISPATCH_AS_HOVER_ENTER, BitSet32(0)); } } // Ensure that we have at least one foreground window or at least one window that cannot be a // foreground target. If we only have windows that are not receiving foreground touches (e.g. we // only have windows getting ACTION_OUTSIDE), then drop the event, because there is no window Loading Loading @@ -2489,13 +2445,10 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } } // Success! Output targets for everything except hovers. if (!isHoverAction) { touchedWindows.insert(touchedWindows.end(), tempTouchState.windows.begin(), tempTouchState.windows.end()); } // Success! Output targets. touchedWindows = tempTouchState.windows; outInjectionResult = InputEventInjectionResult::SUCCEEDED; // Drop the outside or hover touch windows since we will not care about them // in the next iteration. tempTouchState.filterNonAsIsTouchWindows(); Loading @@ -2516,16 +2469,14 @@ Failed: "Conflicting pointer actions: Hover received while pointer was down."); *outConflictingPointerActions = true; } tempTouchState.reset(); if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { // Pointer went up. tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.clearWindowsWithoutPointers(); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. tempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { Loading Loading @@ -2564,6 +2515,9 @@ Failed: mTouchStatesByDisplay.erase(displayId); } // Update hover state. mLastHoverWindowHandle = newHoverWindowHandle; return touchedWindows; } Loading Loading @@ -4855,6 +4809,14 @@ void InputDispatcher::setInputWindowsLocked( updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); if (mLastHoverWindowHandle) { const WindowInfo* lastHoverWindowInfo = mLastHoverWindowHandle->getInfo(); if (lastHoverWindowInfo->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mLastHoverWindowHandle) == windowHandles.end()) { mLastHoverWindowHandle = nullptr; } } std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setInputWindows(displayId, windowHandles); Loading Loading @@ -5302,6 +5264,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { mAnrTracker.clear(); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); mReplacedKeys.clear(); } Loading Loading @@ -6491,6 +6454,7 @@ void InputDispatcher::cancelCurrentTouch() { synthesizeCancelationEventsForAllConnectionsLocked(options); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); } // Wake up poll loop since there might be work to do. mLooper->wake(); Loading services/inputflinger/dispatcher/InputDispatcher.h +3 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,9 @@ private: // prevent unneeded wakeups. AnrTracker mAnrTracker GUARDED_BY(mLock); // Contains the last window which received a hover event. sp<android::gui::WindowInfoHandle> mLastHoverWindowHandle GUARDED_BY(mLock); void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); // If a focused application changes, we should stop counting down the "no focused window" time, // because we will have no way of knowing when the previous application actually added a window. Loading services/inputflinger/dispatcher/TouchState.cpp +0 −55 Original line number Diff line number Diff line Loading @@ -31,30 +31,10 @@ void TouchState::reset() { *this = TouchState(); } void TouchState::removeTouchedPointer(int32_t pointerId) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.pointerIds.clearBit(pointerId); } } void TouchState::clearHoveringPointers() { for (TouchedWindow& touchedWindow : windows) { touchedWindow.clearHoveringPointers(); } } void TouchState::clearWindowsWithoutPointers() { std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty() && !w.hasHoveringPointers(); }); } void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime) { for (TouchedWindow& touchedWindow : windows) { // We do not compare windows by token here because two windows that share the same token // may have a different transform if (touchedWindow.windowHandle == windowHandle) { touchedWindow.targetFlags |= targetFlags; if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) { Loading @@ -79,21 +59,6 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, windows.push_back(touchedWindow); } void TouchState::addHoveringPointerToWindow(const sp<WindowInfoHandle>& windowHandle, int32_t hoveringDeviceId, int32_t hoveringPointerId) { for (TouchedWindow& touchedWindow : windows) { if (touchedWindow.windowHandle == windowHandle) { touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId); return; } } TouchedWindow touchedWindow; touchedWindow.windowHandle = windowHandle; touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId); windows.push_back(touchedWindow); } void TouchState::removeWindowByToken(const sp<IBinder>& token) { for (size_t i = 0; i < windows.size(); i++) { if (windows[i].windowHandle->getToken() == token) { Loading Loading @@ -180,26 +145,6 @@ bool TouchState::isDown() const { [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); }); } std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, int32_t pointerId) const { std::set<sp<WindowInfoHandle>> out; for (const TouchedWindow& window : windows) { if (window.hasHoveringPointer(hoveringDeviceId, pointerId)) { out.insert(window.windowHandle); } } return out; } void TouchState::removeHoveringPointer(int32_t hoveringDeviceId, int32_t hoveringPointerId) { for (TouchedWindow& window : windows) { window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); } std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty() && !w.hasHoveringPointers(); }); } std::string TouchState::dump() const { std::string out; out += StringPrintf("deviceId=%d, source=%s\n", deviceId, Loading services/inputflinger/dispatcher/TouchState.h +0 −11 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <set> #include "TouchedWindow.h" namespace android { Loading @@ -40,16 +39,9 @@ struct TouchState { TouchState& operator=(const TouchState&) = default; void reset(); void clearWindowsWithoutPointers(); void removeTouchedPointer(int32_t pointerId); void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime = std::nullopt); void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t deviceId, int32_t hoveringPointerId); void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId); void clearHoveringPointers(); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); Loading @@ -64,9 +56,6 @@ struct TouchState { sp<android::gui::WindowInfoHandle> getWallpaperWindow() const; // Whether any of the windows are currently being touched bool isDown() const; std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( int32_t deviceId, int32_t pointerId) const; std::string dump() const; }; Loading Loading
include/input/PrintTools.h +0 −6 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <bitset> #include <map> #include <optional> #include <set> Loading @@ -24,11 +23,6 @@ namespace android { template <size_t N> std::string bitsetToString(const std::bitset<N>& bitset) { return bitset.to_string(); } template <typename T> inline std::string constToString(const T& v) { return std::to_string(v); Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +64 −100 Original line number Diff line number Diff line Loading @@ -554,65 +554,6 @@ std::optional<nsecs_t> getDownTime(const EventEntry& eventEntry) { return std::nullopt; } /** * Compare the old touch state to the new touch state, and generate the corresponding touched * windows (== input targets). * If a window had the hovering pointer, but now it doesn't, produce HOVER_EXIT for that window. * If the pointer just entered the new window, produce HOVER_ENTER. * For pointers remaining in the window, produce HOVER_MOVE. */ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState, const TouchState& newTouchState, const MotionEntry& entry) { std::vector<TouchedWindow> out; const int32_t maskedAction = MotionEvent::getActionMasked(entry.action); if (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER && maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE && maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) { // Not a hover event - don't need to do anything return out; } // We should consider all hovering pointers here. But for now, just use the first one const int32_t pointerId = entry.pointerProperties[0].id; std::set<sp<WindowInfoHandle>> oldWindows; if (oldState != nullptr) { oldWindows = oldState->getWindowsWithHoveringPointer(entry.deviceId, pointerId); } std::set<sp<WindowInfoHandle>> newWindows = newTouchState.getWindowsWithHoveringPointer(entry.deviceId, pointerId); // If the pointer is no longer in the new window set, send HOVER_EXIT. for (const sp<WindowInfoHandle>& oldWindow : oldWindows) { if (newWindows.find(oldWindow) == newWindows.end()) { TouchedWindow touchedWindow; touchedWindow.windowHandle = oldWindow; touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_EXIT; touchedWindow.pointerIds.markBit(pointerId); out.push_back(touchedWindow); } } for (const sp<WindowInfoHandle>& newWindow : newWindows) { TouchedWindow touchedWindow; touchedWindow.windowHandle = newWindow; if (oldWindows.find(newWindow) == oldWindows.end()) { // Any windows that have this pointer now, and didn't have it before, should get // HOVER_ENTER touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER; } else { // This pointer was already sent to the window. Use ACTION_HOVER_MOVE. LOG_ALWAYS_FATAL_IF(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE); touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS; } touchedWindow.pointerIds.markBit(pointerId); out.push_back(touchedWindow); } return out; } } // namespace // --- InputDispatcher --- Loading Loading @@ -2142,6 +2083,8 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // Update the touch state as needed based on the properties of the touch event. outInjectionResult = InputEventInjectionResult::PENDING; sp<WindowInfoHandle> newHoverWindowHandle(mLastHoverWindowHandle); sp<WindowInfoHandle> newTouchedWindowHandle; // Copy current touch state into tempTouchState. // This state will be used to update mTouchStatesByDisplay at the end of this function. Loading Loading @@ -2174,7 +2117,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( outInjectionResult = InputEventInjectionResult::FAILED; return touchedWindows; // wrong device } tempTouchState.clearWindowsWithoutPointers(); tempTouchState.reset(); tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; isSplit = false; Loading @@ -2187,21 +2130,14 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( return touchedWindows; // wrong device } if (isHoverAction) { // For hover actions, we will treat 'tempTouchState' as a new state, so let's erase // all of the existing hovering pointers and recompute. tempTouchState.clearHoveringPointers(); } if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { /* Case 1: New splittable pointer going down, or need target for hover or scroll. */ const auto [x, y] = resolveTouchedPosition(entry); const int32_t pointerIndex = getMotionEventActionPointerIndex(action); const bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN; const bool isStylus = isPointerFromStylus(entry, pointerIndex); sp<WindowInfoHandle> newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus, isDown /*addOutsideTargets*/); newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus, isDown /*addOutsideTargets*/); // Handle the case where we did not find a window. if (newTouchedWindowHandle == nullptr) { Loading Loading @@ -2236,6 +2172,15 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( isSplit = !isFromMouse; } // Update hover state. if (newTouchedWindowHandle != nullptr) { if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) { newHoverWindowHandle = nullptr; } else if (isHoverAction) { newHoverWindowHandle = newTouchedWindowHandle; } } std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus); if (newTouchedWindowHandle != nullptr) { Loading @@ -2255,18 +2200,6 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( continue; } if (isHoverAction) { const int32_t pointerId = entry.pointerProperties[0].id; if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) { // Pointer left. Remove it tempTouchState.removeHoveringPointer(entry.deviceId, pointerId); } else { // The "windowHandle" is the target of this hovering pointer. tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointerId); } } // Set target flags. ftl::Flags<InputTarget::Flags> targetFlags = InputTarget::Flags::DISPATCH_AS_IS; Loading @@ -2286,9 +2219,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( // Update the temporary touch state. BitSet32 pointerIds; if (!isHoverAction) { pointerIds.markBit(entry.pointerProperties[pointerIndex].id); } tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds, entry.eventTime); Loading Loading @@ -2324,7 +2255,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( const bool isStylus = isPointerFromStylus(entry, 0 /*pointerIndex*/); sp<WindowInfoHandle> oldTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle(); sp<WindowInfoHandle> newTouchedWindowHandle = newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus); // Verify targeted injection. Loading Loading @@ -2395,11 +2326,36 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } // Update dispatching for hover enter and exit. { std::vector<TouchedWindow> hoveringWindows = getHoveringWindowsLocked(oldState, tempTouchState, entry); touchedWindows.insert(touchedWindows.end(), hoveringWindows.begin(), hoveringWindows.end()); if (newHoverWindowHandle != mLastHoverWindowHandle) { // Let the previous window know that the hover sequence is over, unless we already did // it when dispatching it as is to newTouchedWindowHandle. if (mLastHoverWindowHandle != nullptr && (maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT || mLastHoverWindowHandle != newTouchedWindowHandle)) { if (DEBUG_HOVER) { ALOGD("Sending hover exit event to window %s.", mLastHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, InputTarget::Flags::DISPATCH_AS_HOVER_EXIT, BitSet32(0)); } // Let the new window know that the hover sequence is starting, unless we already did it // when dispatching it as is to newTouchedWindowHandle. if (newHoverWindowHandle != nullptr && (maskedAction != AMOTION_EVENT_ACTION_HOVER_ENTER || newHoverWindowHandle != newTouchedWindowHandle)) { if (DEBUG_HOVER) { ALOGD("Sending hover enter event to window %s.", newHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(newHoverWindowHandle, InputTarget::Flags::DISPATCH_AS_HOVER_ENTER, BitSet32(0)); } } // Ensure that we have at least one foreground window or at least one window that cannot be a // foreground target. If we only have windows that are not receiving foreground touches (e.g. we // only have windows getting ACTION_OUTSIDE), then drop the event, because there is no window Loading Loading @@ -2489,13 +2445,10 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } } // Success! Output targets for everything except hovers. if (!isHoverAction) { touchedWindows.insert(touchedWindows.end(), tempTouchState.windows.begin(), tempTouchState.windows.end()); } // Success! Output targets. touchedWindows = tempTouchState.windows; outInjectionResult = InputEventInjectionResult::SUCCEEDED; // Drop the outside or hover touch windows since we will not care about them // in the next iteration. tempTouchState.filterNonAsIsTouchWindows(); Loading @@ -2516,16 +2469,14 @@ Failed: "Conflicting pointer actions: Hover received while pointer was down."); *outConflictingPointerActions = true; } tempTouchState.reset(); if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) { tempTouchState.deviceId = entry.deviceId; tempTouchState.source = entry.source; } } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { // Pointer went up. tempTouchState.removeTouchedPointer(entry.pointerProperties[0].id); tempTouchState.clearWindowsWithoutPointers(); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. tempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { Loading Loading @@ -2564,6 +2515,9 @@ Failed: mTouchStatesByDisplay.erase(displayId); } // Update hover state. mLastHoverWindowHandle = newHoverWindowHandle; return touchedWindows; } Loading Loading @@ -4855,6 +4809,14 @@ void InputDispatcher::setInputWindowsLocked( updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); if (mLastHoverWindowHandle) { const WindowInfo* lastHoverWindowInfo = mLastHoverWindowHandle->getInfo(); if (lastHoverWindowInfo->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mLastHoverWindowHandle) == windowHandles.end()) { mLastHoverWindowHandle = nullptr; } } std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setInputWindows(displayId, windowHandles); Loading Loading @@ -5302,6 +5264,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { mAnrTracker.clear(); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); mReplacedKeys.clear(); } Loading Loading @@ -6491,6 +6454,7 @@ void InputDispatcher::cancelCurrentTouch() { synthesizeCancelationEventsForAllConnectionsLocked(options); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); } // Wake up poll loop since there might be work to do. mLooper->wake(); Loading
services/inputflinger/dispatcher/InputDispatcher.h +3 −0 Original line number Diff line number Diff line Loading @@ -530,6 +530,9 @@ private: // prevent unneeded wakeups. AnrTracker mAnrTracker GUARDED_BY(mLock); // Contains the last window which received a hover event. sp<android::gui::WindowInfoHandle> mLastHoverWindowHandle GUARDED_BY(mLock); void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); // If a focused application changes, we should stop counting down the "no focused window" time, // because we will have no way of knowing when the previous application actually added a window. Loading
services/inputflinger/dispatcher/TouchState.cpp +0 −55 Original line number Diff line number Diff line Loading @@ -31,30 +31,10 @@ void TouchState::reset() { *this = TouchState(); } void TouchState::removeTouchedPointer(int32_t pointerId) { for (TouchedWindow& touchedWindow : windows) { touchedWindow.pointerIds.clearBit(pointerId); } } void TouchState::clearHoveringPointers() { for (TouchedWindow& touchedWindow : windows) { touchedWindow.clearHoveringPointers(); } } void TouchState::clearWindowsWithoutPointers() { std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty() && !w.hasHoveringPointers(); }); } void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime) { for (TouchedWindow& touchedWindow : windows) { // We do not compare windows by token here because two windows that share the same token // may have a different transform if (touchedWindow.windowHandle == windowHandle) { touchedWindow.targetFlags |= targetFlags; if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) { Loading @@ -79,21 +59,6 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, windows.push_back(touchedWindow); } void TouchState::addHoveringPointerToWindow(const sp<WindowInfoHandle>& windowHandle, int32_t hoveringDeviceId, int32_t hoveringPointerId) { for (TouchedWindow& touchedWindow : windows) { if (touchedWindow.windowHandle == windowHandle) { touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId); return; } } TouchedWindow touchedWindow; touchedWindow.windowHandle = windowHandle; touchedWindow.addHoveringPointer(hoveringDeviceId, hoveringPointerId); windows.push_back(touchedWindow); } void TouchState::removeWindowByToken(const sp<IBinder>& token) { for (size_t i = 0; i < windows.size(); i++) { if (windows[i].windowHandle->getToken() == token) { Loading Loading @@ -180,26 +145,6 @@ bool TouchState::isDown() const { [](const TouchedWindow& window) { return !window.pointerIds.isEmpty(); }); } std::set<sp<WindowInfoHandle>> TouchState::getWindowsWithHoveringPointer(int32_t hoveringDeviceId, int32_t pointerId) const { std::set<sp<WindowInfoHandle>> out; for (const TouchedWindow& window : windows) { if (window.hasHoveringPointer(hoveringDeviceId, pointerId)) { out.insert(window.windowHandle); } } return out; } void TouchState::removeHoveringPointer(int32_t hoveringDeviceId, int32_t hoveringPointerId) { for (TouchedWindow& window : windows) { window.removeHoveringPointer(hoveringDeviceId, hoveringPointerId); } std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty() && !w.hasHoveringPointers(); }); } std::string TouchState::dump() const { std::string out; out += StringPrintf("deviceId=%d, source=%s\n", deviceId, Loading
services/inputflinger/dispatcher/TouchState.h +0 −11 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <set> #include "TouchedWindow.h" namespace android { Loading @@ -40,16 +39,9 @@ struct TouchState { TouchState& operator=(const TouchState&) = default; void reset(); void clearWindowsWithoutPointers(); void removeTouchedPointer(int32_t pointerId); void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime = std::nullopt); void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t deviceId, int32_t hoveringPointerId); void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId); void clearHoveringPointers(); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); Loading @@ -64,9 +56,6 @@ struct TouchState { sp<android::gui::WindowInfoHandle> getWallpaperWindow() const; // Whether any of the windows are currently being touched bool isDown() const; std::set<sp<android::gui::WindowInfoHandle>> getWindowsWithHoveringPointer( int32_t deviceId, int32_t pointerId) const; std::string dump() const; }; Loading