diff options
author | 2025-02-03 05:34:28 -0800 | |
---|---|---|
committer | 2025-02-03 05:34:28 -0800 | |
commit | 1c0656dfed9cc1a1a4f8597e10afad7f2dcadc69 (patch) | |
tree | 0a2004bb082b49affa9586579b2a6b87c0ba80d1 | |
parent | 3c090f80737df49e2b20861b4f5a9bf318fec43f (diff) | |
parent | 403a3d7525e979cfe282796903b87b2ca8c10922 (diff) |
Merge changes I4db90c62,Ib32ee292 into main
* changes:
[13/n Dispatcher refactor] Move TouchState to DispatcherTouchState
[12/n Dispatcher refactor] Introduce static DispatcherTouchState
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 308 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 110 |
2 files changed, 247 insertions, 171 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 098019fc80..56be2e657f 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1267,8 +1267,9 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t& nextWakeupTime) { if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) { // The event is stale. However, only drop stale events if there isn't an ongoing // gesture. That would allow us to complete the processing of the current stroke. - const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId); - if (touchStateIt != mTouchStatesByDisplay.end()) { + const auto touchStateIt = + mTouchStates.mTouchStatesByDisplay.find(motionEntry->displayId); + if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; if (!touchState.hasTouchingPointers(motionEntry->deviceId) && !touchState.hasHoveringPointers(motionEntry->deviceId)) { @@ -1355,7 +1356,8 @@ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEnt // Alternatively, maybe there's a spy window that could handle this event. const std::vector<sp<WindowInfoHandle>> touchedSpies = mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, - motionEntry.deviceId, mTouchStatesByDisplay); + motionEntry.deviceId, + mTouchStates.mTouchStatesByDisplay); for (const auto& windowHandle : touchedSpies) { const std::shared_ptr<Connection> connection = mConnectionManager.getConnection(windowHandle->getToken()); @@ -1480,15 +1482,16 @@ sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findTouchedWindowAt( return nullptr; } -std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked( - ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow, - int32_t pointerId) const { +std::vector<InputTarget> InputDispatcher::DispatcherTouchState::findOutsideTargets( + ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow, + int32_t pointerId, const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, std::function<void()> dump) { if (touchedWindow == nullptr) { return {}; } // Traverse windows from front to back until we encounter the touched window. std::vector<InputTarget> outsideTargets; - const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId); + const auto& windowHandles = windowInfos.getWindowHandlesForDisplay(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { if (windowHandle == touchedWindow) { // Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window @@ -1500,9 +1503,13 @@ std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked( if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) { std::bitset<MAX_POINTER_ID + 1> pointerIds; pointerIds.set(pointerId); - addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE, - ftl::Flags<InputTarget::Flags>(), pointerIds, - /*firstDownTimeInTarget=*/std::nullopt, outsideTargets); + DispatcherTouchState::addPointerWindowTarget(windowHandle, + InputTarget::DispatchMode::OUTSIDE, + ftl::Flags<InputTarget::Flags>(), + pointerIds, + /*firstDownTimeInTarget=*/std::nullopt, + connections, windowInfos, dump, + outsideTargets); } } return outsideTargets; @@ -1709,7 +1716,7 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, synthesizeCancelationEventsForAllConnectionsLocked(options); // Remove all active pointers from this device - for (auto& [_, touchState] : mTouchStatesByDisplay) { + for (auto& [_, touchState] : mTouchStates.mTouchStatesByDisplay) { touchState.removeAllPointersForDevice(entry.deviceId); } return true; @@ -2073,7 +2080,16 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, } Result<std::vector<InputTarget>, InputEventInjectionResult> result = - findTouchedWindowTargetsLocked(currentTime, *entry); + mTouchStates + .findTouchedWindowTargets(currentTime, *entry, mConnectionManager, + mWindowInfos, + mDragState ? mDragState->dragWindow : nullptr, + std::bind_front(&InputDispatcher:: + addDragEventLocked, + this), + std::bind_front(&InputDispatcher:: + logDispatchStateLocked, + this)); if (result.ok()) { inputTargets = std::move(*result); @@ -2318,7 +2334,8 @@ InputDispatcher::findFocusedWindowTargetLocked(nsecs_t currentTime, const EventE } // Drop key events if requested by input feature - if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) { + if (focusedWindowHandle != nullptr && + shouldDropInput(entry, focusedWindowHandle, mWindowInfos)) { return injectionError(InputEventInjectionResult::FAILED); } @@ -2387,8 +2404,12 @@ InputDispatcher::findFocusedWindowTargetLocked(nsecs_t currentTime, const EventE return focusedWindowHandle; } -base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult> -InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) { +base::Result<std::vector<InputTarget>, os::InputEventInjectionResult> +InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( + nsecs_t currentTime, const MotionEntry& entry, const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, + const sp<android::gui::WindowInfoHandle> dragWindow, + std::function<void(const MotionEntry&)> addDragEvent, std::function<void()> dump) { ATRACE_CALL(); std::vector<InputTarget> targets; @@ -2448,10 +2469,12 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio // be a pointer that would generate ACTION_DOWN, *and* touch should not already be down. const bool isStylus = isPointerFromStylus(entry, pointerIndex); sp<WindowInfoHandle> newTouchedWindowHandle = - mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus); + windowInfos.findTouchedWindowAt(displayId, x, y, isStylus); if (isDown) { - targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id); + targets += DispatcherTouchState::findOutsideTargets(displayId, newTouchedWindowHandle, + pointer.id, connections, + windowInfos, dump); } LOG_IF(INFO, newTouchedWindowHandle == nullptr) << "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y) @@ -2464,8 +2487,8 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio } std::vector<sp<WindowInfoHandle>> newTouchedWindows = - mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, - mTouchStatesByDisplay); + windowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, + mTouchStatesByDisplay); if (newTouchedWindowHandle != nullptr) { // Process the foreground window first so that it is the first to receive the event. newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle); @@ -2478,7 +2501,8 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio } for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { - if (!canWindowReceiveMotionLocked(windowHandle, entry)) { + if (!canWindowReceiveMotion(windowHandle, entry, connections, windowInfos, + mTouchStatesByDisplay)) { continue; } @@ -2489,21 +2513,9 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio } // Set target flags. - ftl::Flags<InputTarget::Flags> targetFlags; - - if (canReceiveForegroundTouches(*windowHandle->getInfo())) { - // There should only be one touched window that can be "foreground" for the pointer. - targetFlags |= InputTarget::Flags::FOREGROUND; - } - - if (isSplit) { - targetFlags |= InputTarget::Flags::SPLIT; - } - if (mWindowInfos.isWindowObscuredAtPoint(windowHandle, x, y)) { - targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED; - } else if (mWindowInfos.isWindowObscured(windowHandle)) { - targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; - } + ftl::Flags<InputTarget::Flags> targetFlags = + DispatcherTouchState::getTargetFlags(windowHandle, {x, y}, isSplit, + windowInfos); // Update the temporary touch state. @@ -2521,7 +2533,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio if (!addResult.ok()) { LOG(ERROR) << "Error while processing " << entry << " for " << windowHandle->getName(); - logDispatchStateLocked(); + dump(); } // If this is the pointer going down and the touched window has a wallpaper // then also add the touched wallpaper windows so they are locked in for the @@ -2533,7 +2545,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio windowHandle->getInfo()->inputConfig.test( gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) { sp<WindowInfoHandle> wallpaper = - mWindowInfos.findWallpaperWindowBelow(windowHandle); + windowInfos.findWallpaperWindowBelow(windowHandle); if (wallpaper != nullptr) { ftl::Flags<InputTarget::Flags> wallpaperFlags = InputTarget::Flags::WINDOW_IS_OBSCURED | @@ -2592,7 +2604,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio tempTouchState.removeHoveringPointer(entry.deviceId, pointerId); } - addDragEventLocked(entry); + addDragEvent(entry); // Check whether touches should slip outside of the current foreground window. if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 && @@ -2603,7 +2615,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio tempTouchState.getFirstForegroundWindowHandle(entry.deviceId); LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr); sp<WindowInfoHandle> newTouchedWindowHandle = - mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus); + windowInfos.findTouchedWindowAt(displayId, x, y, isStylus); // Verify targeted injection. if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) { @@ -2613,7 +2625,8 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio // Do not slide events to the window which can not receive motion event if (newTouchedWindowHandle != nullptr && - !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) { + !canWindowReceiveMotion(newTouchedWindowHandle, entry, connections, windowInfos, + mTouchStatesByDisplay)) { newTouchedWindowHandle = nullptr; } @@ -2630,26 +2643,18 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio const TouchedWindow& touchedWindow = tempTouchState.getTouchedWindow(oldTouchedWindowHandle); - addPointerWindowTargetLocked(oldTouchedWindowHandle, - InputTarget::DispatchMode::SLIPPERY_EXIT, - ftl::Flags<InputTarget::Flags>(), pointerIds, - touchedWindow.getDownTimeInTarget(entry.deviceId), - targets); + DispatcherTouchState:: + addPointerWindowTarget(oldTouchedWindowHandle, + InputTarget::DispatchMode::SLIPPERY_EXIT, + ftl::Flags<InputTarget::Flags>(), pointerIds, + touchedWindow.getDownTimeInTarget(entry.deviceId), + connections, windowInfos, dump, targets); // Make a slippery entrance into the new window. - ftl::Flags<InputTarget::Flags> targetFlags; - if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) { - targetFlags |= InputTarget::Flags::FOREGROUND; - } - if (isSplit) { - targetFlags |= InputTarget::Flags::SPLIT; - } - if (mWindowInfos.isWindowObscuredAtPoint(newTouchedWindowHandle, x, y)) { - targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED; - } else if (mWindowInfos.isWindowObscured(newTouchedWindowHandle)) { - targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; - } + ftl::Flags<InputTarget::Flags> targetFlags = + DispatcherTouchState::getTargetFlags(newTouchedWindowHandle, {x, y}, + isSplit, windowInfos); tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, InputTarget::DispatchMode::SLIPPERY_ENTER, @@ -2657,8 +2662,10 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio entry.eventTime); // Check if the wallpaper window should deliver the corresponding event. - slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle, - tempTouchState, entry, targets); + DispatcherTouchState::slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, + newTouchedWindowHandle, tempTouchState, + entry, targets, connections, windowInfos, + dump); tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id, oldTouchedWindowHandle); } @@ -2671,7 +2678,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]}; for (TouchedWindow& touchedWindow : tempTouchState.windows) { // Ignore drag window for it should just track one pointer. - if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) { + if (dragWindow == touchedWindow.windowHandle) { continue; } if (!touchedWindow.hasTouchingPointers(entry.deviceId)) { @@ -2685,17 +2692,17 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio // Update dispatching for hover enter and exit. { std::vector<TouchedWindow> hoveringWindows = - getHoveringWindowsLocked(oldState, tempTouchState, entry, - std::bind_front(&InputDispatcher::logDispatchStateLocked, - this)); + getHoveringWindowsLocked(oldState, tempTouchState, entry, dump); // Hardcode to single hovering pointer for now. std::bitset<MAX_POINTER_ID + 1> pointerIds; pointerIds.set(entry.pointerProperties[0].id); for (const TouchedWindow& touchedWindow : hoveringWindows) { - addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode, - touchedWindow.targetFlags, pointerIds, - touchedWindow.getDownTimeInTarget(entry.deviceId), - targets); + DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle, + touchedWindow.dispatchMode, + touchedWindow.targetFlags, pointerIds, + touchedWindow.getDownTimeInTarget( + entry.deviceId), + connections, windowInfos, dump, targets); } } @@ -2724,7 +2731,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio for (InputTarget& target : targets) { if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) { sp<WindowInfoHandle> targetWindow = - mWindowInfos.findWindowHandle(target.connection->getToken()); + windowInfos.findWindowHandle(target.connection->getToken()); if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) { target.flags |= InputTarget::Flags::ZERO_COORDS; } @@ -2748,9 +2755,13 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio if (touchingPointers.empty()) { continue; } - addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode, - touchedWindow.targetFlags, getPointerIds(touchingPointers), - touchedWindow.getDownTimeInTarget(entry.deviceId), targets); + DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle, + touchedWindow.dispatchMode, + touchedWindow.targetFlags, + getPointerIds(touchingPointers), + touchedWindow.getDownTimeInTarget( + entry.deviceId), + connections, windowInfos, dump, targets); } // During targeted injection, only allow owned targets to receive events @@ -2953,11 +2964,12 @@ void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHa } } -void InputDispatcher::addPointerWindowTargetLocked( +void InputDispatcher::DispatcherTouchState::addPointerWindowTarget( const sp<android::gui::WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget, - std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) { + const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos, + std::function<void()> dump, std::vector<InputTarget>& inputTargets) { if (pointerIds.none()) { for (const auto& target : inputTargets) { LOG(INFO) << "Target: " << target; @@ -2982,19 +2994,17 @@ void InputDispatcher::addPointerWindowTargetLocked( it = inputTargets.end(); } - const WindowInfo* windowInfo = windowHandle->getInfo(); + const WindowInfo& windowInfo = *windowHandle->getInfo(); if (it == inputTargets.end()) { - std::shared_ptr<Connection> connection = - mConnectionManager.getConnection(windowHandle->getToken()); + std::shared_ptr<Connection> connection = connections.getConnection(windowInfo.token); if (connection == nullptr) { - ALOGW("Not creating InputTarget for %s, no input channel", - windowHandle->getName().c_str()); + ALOGW("Not creating InputTarget for %s, no input channel", windowInfo.name.c_str()); return; } inputTargets.push_back( createInputTarget(connection, windowHandle, dispatchMode, targetFlags, - mWindowInfos.getRawTransform(*windowHandle->getInfo()), + windowInfos.getRawTransform(*windowHandle->getInfo()), firstDownTimeInTarget)); it = inputTargets.end() - 1; } @@ -3007,14 +3017,14 @@ void InputDispatcher::addPointerWindowTargetLocked( LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string() << ", it=" << *it; } - if (it->globalScaleFactor != windowInfo->globalScaleFactor) { + if (it->globalScaleFactor != windowInfo.globalScaleFactor) { LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor - << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor; + << ", windowInfo->globalScaleFactor=" << windowInfo.globalScaleFactor; } - Result<void> result = it->addPointers(pointerIds, windowInfo->transform); + Result<void> result = it->addPointers(pointerIds, windowInfo.transform); if (!result.ok()) { - logDispatchStateLocked(); + dump(); LOG(FATAL) << result.error().message(); } } @@ -4069,7 +4079,7 @@ void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( // Generate cancellations for touched windows first. This is to avoid generating cancellations // through a non-touched window if there are more than one window for an input channel. if (cancelPointers) { - for (const auto& [displayId, touchState] : mTouchStatesByDisplay) { + for (const auto& [displayId, touchState] : mTouchStates.mTouchStatesByDisplay) { if (options.displayId.has_value() && options.displayId != displayId) { continue; } @@ -4204,9 +4214,15 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0); mDragState.reset(); } - addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS, - ftl::Flags<InputTarget::Flags>(), pointerIds, - motionEntry.downTime, targets); + DispatcherTouchState:: + addPointerWindowTarget(window, InputTarget::DispatchMode::AS_IS, + ftl::Flags<InputTarget::Flags>(), pointerIds, + motionEntry.downTime, mConnectionManager, + mWindowInfos, + std::bind_front(&InputDispatcher:: + logDispatchStateLocked, + this), + targets); } else { targets.emplace_back(fallbackTarget); // Since we don't have a window, use the display transform as the raw transform. @@ -4268,7 +4284,8 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( } const auto [_, touchedWindowState, displayId] = - findTouchStateWindowAndDisplay(connection->getToken(), mTouchStatesByDisplay); + findTouchStateWindowAndDisplay(connection->getToken(), + mTouchStates.mTouchStatesByDisplay); if (touchedWindowState == nullptr) { LOG(FATAL) << __func__ << ": Touch state is out of sync: No touched window for token"; } @@ -4290,9 +4307,14 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( pointerIndex++) { pointerIds.set(motionEntry.pointerProperties[pointerIndex].id); } - addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS, - targetFlags, pointerIds, motionEntry.downTime, - targets); + DispatcherTouchState:: + addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::AS_IS, + targetFlags, pointerIds, motionEntry.downTime, + mConnectionManager, mWindowInfos, + std::bind_front(&InputDispatcher:: + logDispatchStateLocked, + this), + targets); } else { targets.emplace_back(connection, targetFlags); // Since we don't have a window, use the display transform as the raw transform. @@ -4559,8 +4581,8 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) { if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) { // Set the flag anyway if we already have an ongoing gesture. That would allow us to // complete the processing of the current stroke. - const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId); - if (touchStateIt != mTouchStatesByDisplay.end()) { + const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(args.displayId); + if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; if (touchState.hasTouchingPointers(args.deviceId) || touchState.hasHoveringPointers(args.deviceId)) { @@ -4871,8 +4893,8 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) { // Set the flag anyway if we already have an ongoing motion gesture. That // would allow us to complete the processing of the current stroke. - const auto touchStateIt = mTouchStatesByDisplay.find(displayId); - if (touchStateIt != mTouchStatesByDisplay.end()) { + const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId); + if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; if (touchState.hasTouchingPointers(resolvedDeviceId) || touchState.hasHoveringPointers(resolvedDeviceId)) { @@ -5266,9 +5288,11 @@ std::string InputDispatcher::DispatcherWindowInfo::dumpDisplayAndWindowInfo() co return dump; } -bool InputDispatcher::canWindowReceiveMotionLocked( +bool InputDispatcher::canWindowReceiveMotion( const sp<android::gui::WindowInfoHandle>& window, - const android::inputdispatcher::MotionEntry& motionEntry) const { + const android::inputdispatcher::MotionEntry& motionEntry, + const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos, + const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates) { const WindowInfo& info = *window->getInfo(); // Skip spy window targets that are not valid for targeted injection. @@ -5287,7 +5311,7 @@ bool InputDispatcher::canWindowReceiveMotionLocked( return false; } - std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken()); + std::shared_ptr<Connection> connection = connections.getConnection(window->getToken()); if (connection == nullptr) { ALOGW("Not sending touch to %s because there's no corresponding connection", window->getName().c_str()); @@ -5302,8 +5326,8 @@ bool InputDispatcher::canWindowReceiveMotionLocked( // Drop events that can't be trusted due to occlusion const auto [x, y] = resolveTouchedPosition(motionEntry); DispatcherWindowInfo::TouchOcclusionInfo occlusionInfo = - mWindowInfos.computeTouchOcclusionInfo(window, x, y); - if (!mWindowInfos.isTouchTrusted(occlusionInfo)) { + windowInfos.computeTouchOcclusionInfo(window, x, y); + if (!windowInfos.isTouchTrusted(occlusionInfo)) { if (DEBUG_TOUCH_OCCLUSION) { ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x, y); for (const auto& log : occlusionInfo.debugInfo) { @@ -5316,13 +5340,13 @@ bool InputDispatcher::canWindowReceiveMotionLocked( } // Drop touch events if requested by input feature - if (shouldDropInput(motionEntry, window)) { + if (shouldDropInput(motionEntry, window, windowInfos)) { return false; } // Ignore touches if stylus is down anywhere on screen if (info.inputConfig.test(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH) && - isStylusActiveInDisplay(info.displayId, mTouchStatesByDisplay)) { + isStylusActiveInDisplay(info.displayId, touchStates)) { LOG(INFO) << "Dropping touch from " << window->getName() << " because stylus is active"; return false; } @@ -5446,7 +5470,8 @@ void InputDispatcher::setInputWindowsLocked( onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle); } - if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) { + if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId); + it != mTouchStates.mTouchStatesByDisplay.end()) { TouchState& state = it->second; for (size_t i = 0; i < state.windows.size();) { TouchedWindow& touchedWindow = state.windows[i]; @@ -5487,7 +5512,8 @@ void InputDispatcher::setInputWindowsLocked( // Check if the hovering should stop because the window is no longer eligible to receive it // (for example, if the touchable region changed) - if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) { + if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId); + it != mTouchStates.mTouchStatesByDisplay.end()) { TouchState& state = it->second; for (TouchedWindow& touchedWindow : state.windows) { std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf( @@ -5793,7 +5819,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s // Find the target touch state and touched window by fromToken. auto [state, touchedWindow, displayId] = - findTouchStateWindowAndDisplay(fromToken, mTouchStatesByDisplay); + findTouchStateWindowAndDisplay(fromToken, mTouchStates.mTouchStatesByDisplay); if (state == nullptr || touchedWindow == nullptr) { ALOGD("Touch transfer failed because from window is not being touched."); @@ -5885,11 +5911,10 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s * Return null if there are no windows touched on that display, or if more than one foreground * window is being touched. */ -sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindow( - const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay, - ui::LogicalDisplayId displayId) { - const auto stateIt = touchStatesByDisplay.find(displayId); - if (stateIt == touchStatesByDisplay.end()) { +sp<WindowInfoHandle> InputDispatcher::DispatcherTouchState::findTouchedForegroundWindow( + ui::LogicalDisplayId displayId) const { + const auto stateIt = mTouchStatesByDisplay.find(displayId); + if (stateIt == mTouchStatesByDisplay.end()) { ALOGI("No touch state on display %s", displayId.toString().c_str()); return nullptr; } @@ -5925,7 +5950,7 @@ bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken return false; } - sp<WindowInfoHandle> from = findTouchedForegroundWindow(mTouchStatesByDisplay, displayId); + sp<WindowInfoHandle> from = mTouchStates.findTouchedForegroundWindow(displayId); if (from == nullptr) { ALOGE("Could not find a source window in %s for %p", __func__, destChannelToken.get()); return false; @@ -5953,7 +5978,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { resetNoFocusedWindowTimeoutLocked(); mAnrTracker.clear(); - mTouchStatesByDisplay.clear(); + mTouchStates.mTouchStatesByDisplay.clear(); } void InputDispatcher::logDispatchStateLocked() const { @@ -6011,9 +6036,9 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { dump += mFocusResolver.dump(); dump += dumpPointerCaptureStateLocked(); - if (!mTouchStatesByDisplay.empty()) { + if (!mTouchStates.mTouchStatesByDisplay.empty()) { dump += StringPrintf(INDENT "TouchStatesByDisplay:\n"); - for (const auto& [displayId, state] : mTouchStatesByDisplay) { + for (const auto& [displayId, state] : mTouchStates.mTouchStatesByDisplay) { std::string touchStateDump = addLinePrefix(state.dump(), INDENT2); dump += INDENT2 + displayId.toString() + " : " + touchStateDump; } @@ -6222,7 +6247,7 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) { } auto [statePtr, windowPtr, displayId] = - findTouchStateWindowAndDisplay(token, mTouchStatesByDisplay); + findTouchStateWindowAndDisplay(token, mTouchStates.mTouchStatesByDisplay); if (statePtr == nullptr || windowPtr == nullptr) { LOG(WARNING) << "Attempted to pilfer points from a channel without any on-going pointer streams." @@ -7037,12 +7062,13 @@ void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) mLooper->wake(); } -bool InputDispatcher::shouldDropInput( - const EventEntry& entry, const sp<android::gui::WindowInfoHandle>& windowHandle) const { +bool InputDispatcher::shouldDropInput(const EventEntry& entry, + const sp<WindowInfoHandle>& windowHandle, + const DispatcherWindowInfo& windowInfos) { if (windowHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::DROP_INPUT) || (windowHandle->getInfo()->inputConfig.test( WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) && - mWindowInfos.isWindowObscured(windowHandle))) { + windowInfos.isWindowObscured(windowHandle))) { ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on " "display %s.", ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(), @@ -7067,7 +7093,7 @@ void InputDispatcher::cancelCurrentTouch() { "cancel current touch", traceContext.getTracker()); synthesizeCancelationEventsForAllConnectionsLocked(options); - mTouchStatesByDisplay.clear(); + mTouchStates.mTouchStatesByDisplay.clear(); } // Wake up poll loop since there might be work to do. mLooper->wake(); @@ -7078,11 +7104,11 @@ void InputDispatcher::setMonitorDispatchingTimeoutForTest(std::chrono::nanosecon mMonitorDispatchingTimeout = timeout; } -void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags, - const sp<WindowInfoHandle>& oldWindowHandle, - const sp<WindowInfoHandle>& newWindowHandle, - TouchState& state, const MotionEntry& entry, - std::vector<InputTarget>& targets) const { +void InputDispatcher::DispatcherTouchState::slipWallpaperTouch( + ftl::Flags<InputTarget::Flags> targetFlags, const sp<WindowInfoHandle>& oldWindowHandle, + const sp<WindowInfoHandle>& newWindowHandle, TouchState& state, const MotionEntry& entry, + std::vector<InputTarget>& targets, const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, std::function<void()> dump) { LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry; const DeviceId deviceId = entry.deviceId; const PointerProperties& pointerProperties = entry.pointerProperties[0]; @@ -7095,16 +7121,19 @@ void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFl const sp<WindowInfoHandle> oldWallpaper = oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr; const sp<WindowInfoHandle> newWallpaper = - newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr; + newHasWallpaper ? windowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr; if (oldWallpaper == newWallpaper) { return; } if (oldWallpaper != nullptr) { const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper); - addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT, - oldTouchedWindow.targetFlags, getPointerIds(pointers), - oldTouchedWindow.getDownTimeInTarget(deviceId), targets); + DispatcherTouchState::addPointerWindowTarget(oldWallpaper, + InputTarget::DispatchMode::SLIPPERY_EXIT, + oldTouchedWindow.targetFlags, + getPointerIds(pointers), + oldTouchedWindow.getDownTimeInTarget(deviceId), + connections, windowInfos, dump, targets); state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper); } @@ -7199,8 +7228,8 @@ bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token, ui::LogicalDisplayId displayId, DeviceId deviceId, int32_t pointerId) { std::scoped_lock _l(mLock); - auto touchStateIt = mTouchStatesByDisplay.find(displayId); - if (touchStateIt == mTouchStatesByDisplay.end()) { + auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId); + if (touchStateIt == mTouchStates.mTouchStatesByDisplay.end()) { return false; } for (const TouchedWindow& window : touchStateIt->second.windows) { @@ -7355,4 +7384,23 @@ void InputDispatcher::DispatcherWindowInfo::setMaximumObscuringOpacityForTouch(f mMaximumObscuringOpacityForTouch = opacity; } +ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetFlags( + const sp<WindowInfoHandle>& targetWindow, vec2 targetPosition, bool isSplit, + const DispatcherWindowInfo& windowInfos) { + ftl::Flags<InputTarget::Flags> targetFlags; + if (canReceiveForegroundTouches(*targetWindow->getInfo())) { + // There should only be one touched window that can be "foreground" for the pointer. + targetFlags |= InputTarget::Flags::FOREGROUND; + } + if (isSplit) { + targetFlags |= InputTarget::Flags::SPLIT; + } + if (windowInfos.isWindowObscuredAtPoint(targetWindow, targetPosition.x, targetPosition.y)) { + targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED; + } else if (windowInfos.isWindowObscured(targetWindow)) { + targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; + } + return targetFlags; +} + } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 415f4c8031..58c850929f 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -350,6 +350,67 @@ private: DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock); + class DispatcherTouchState { + public: + static void addPointerWindowTarget(const sp<android::gui::WindowInfoHandle>& windowHandle, + InputTarget::DispatchMode dispatchMode, + ftl::Flags<InputTarget::Flags> targetFlags, + std::bitset<MAX_POINTER_ID + 1> pointerIds, + std::optional<nsecs_t> firstDownTimeInTarget, + const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, + std::function<void()> dump, + std::vector<InputTarget>& inputTargets); + + base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult> + findTouchedWindowTargets(nsecs_t currentTime, const MotionEntry& entry, + const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, + const sp<android::gui::WindowInfoHandle> dragWindow, + std::function<void(const MotionEntry&)> addDragEvent, + std::function<void()> dump); + + sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow( + ui::LogicalDisplayId displayId) const; + + std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay; + + private: + static std::vector<InputTarget> findOutsideTargets( + ui::LogicalDisplayId displayId, + const sp<android::gui::WindowInfoHandle>& touchedWindow, int32_t pointerId, + const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos, + std::function<void()> dump); + + /** + * Slip the wallpaper touch if necessary. + * + * @param targetFlags the target flags + * @param oldWindowHandle the old window that the touch slipped out of + * @param newWindowHandle the new window that the touch is slipping into + * @param state the current touch state. This will be updated if necessary to reflect the + * new windows that are receiving touch. + * @param deviceId the device id of the current motion being processed + * @param pointerProperties the pointer properties of the current motion being processed + * @param targets the current targets to add the walpaper ones to + * @param eventTime the new downTime for the wallpaper target + */ + static void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags, + const sp<android::gui::WindowInfoHandle>& oldWindowHandle, + const sp<android::gui::WindowInfoHandle>& newWindowHandle, + TouchState& state, const MotionEntry& entry, + std::vector<InputTarget>& targets, + const ConnectionManager& connections, + const DispatcherWindowInfo& windowInfos, + std::function<void()> dump); + + static ftl::Flags<InputTarget::Flags> getTargetFlags( + const sp<android::gui::WindowInfoHandle>& targetWindow, vec2 targetPosition, + bool isSplit, const DispatcherWindowInfo& windowInfos); + }; + + DispatcherTouchState mTouchStates GUARDED_BY(mLock); + // With each iteration, InputDispatcher nominally processes one queued event, // a timeout, or a response from an input consumer. // This method should only be called on the input dispatcher's own thread. @@ -378,14 +439,6 @@ private: // to transfer focus to a new application. std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock); - std::vector<InputTarget> findOutsideTargetsLocked( - ui::LogicalDisplayId displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow, - int32_t pointerId) const REQUIRES(mLock); - - static sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow( - const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay, - ui::LogicalDisplayId displayId); - status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock); const HmacKeyManager mHmacKeyManager; @@ -470,8 +523,11 @@ private: sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked( ui::LogicalDisplayId displayId) const REQUIRES(mLock); - bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window, - const MotionEntry& motionEntry) const REQUIRES(mLock); + + static bool canWindowReceiveMotion( + const sp<android::gui::WindowInfoHandle>& window, const MotionEntry& motionEntry, + const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos, + const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates); // Returns all the input targets (with their respective input channels) from the window handles // passed as argument. @@ -486,8 +542,6 @@ private: const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles, ui::LogicalDisplayId displayId) REQUIRES(mLock); - std::unordered_map<ui::LogicalDisplayId /*displayId*/, TouchState> mTouchStatesByDisplay - GUARDED_BY(mLock); std::unique_ptr<DragState> mDragState GUARDED_BY(mLock); void setFocusedApplicationLocked( @@ -627,20 +681,12 @@ private: base::Result<sp<android::gui::WindowInfoHandle>, android::os::InputEventInjectionResult> findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry, nsecs_t& nextWakeupTime) REQUIRES(mLock); - base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult> - findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock); void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const REQUIRES(mLock); - void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, - InputTarget::DispatchMode dispatchMode, - ftl::Flags<InputTarget::Flags> targetFlags, - std::bitset<MAX_POINTER_ID + 1> pointerIds, - std::optional<nsecs_t> firstDownTimeInTarget, - std::vector<InputTarget>& inputTargets) const REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, ui::LogicalDisplayId displayId) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); @@ -652,9 +698,9 @@ private: std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle, const sp<android::gui::WindowInfoHandle>& windowHandle); - bool shouldDropInput(const EventEntry& entry, - const sp<android::gui::WindowInfoHandle>& windowHandle) const - REQUIRES(mLock); + static bool shouldDropInput(const EventEntry& entry, + const sp<android::gui::WindowInfoHandle>& windowHandle, + const DispatcherWindowInfo& windowInfo); // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work @@ -774,24 +820,6 @@ private: sp<InputReporterInterface> mReporter; - /** - * Slip the wallpaper touch if necessary. - * - * @param targetFlags the target flags - * @param oldWindowHandle the old window that the touch slipped out of - * @param newWindowHandle the new window that the touch is slipping into - * @param state the current touch state. This will be updated if necessary to reflect the new - * windows that are receiving touch. - * @param deviceId the device id of the current motion being processed - * @param pointerProperties the pointer properties of the current motion being processed - * @param targets the current targets to add the walpaper ones to - * @param eventTime the new downTime for the wallpaper target - */ - void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags, - const sp<android::gui::WindowInfoHandle>& oldWindowHandle, - const sp<android::gui::WindowInfoHandle>& newWindowHandle, - TouchState& state, const MotionEntry& entry, - std::vector<InputTarget>& targets) const REQUIRES(mLock); void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags, ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<android::gui::WindowInfoHandle> fromWindowHandle, |