Loading services/inputflinger/dispatcher/InputDispatcher.cpp +100 −221 Original line number Diff line number Diff line Loading @@ -417,20 +417,6 @@ KeyEvent createKeyEvent(const KeyEntry& entry) { return event; } std::optional<int32_t> findMonitorPidByToken( const std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay, const sp<IBinder>& token) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return monitor.pid; } } } return std::nullopt; } bool shouldReportMetricsForConnection(const Connection& connection) { // Do not keep track of gesture monitors. They receive every event and would disproportionately // affect the statistics. Loading Loading @@ -948,15 +934,16 @@ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEnt return true; } // Alternatively, maybe there's a gesture monitor that could handle this event for (const auto& monitor : getValueByKey(mGestureMonitorsByDisplay, displayId)) { sp<Connection> connection = getConnectionLocked(monitor.inputChannel->getConnectionToken()); // Alternatively, maybe there's a spy window that could handle this event. const std::vector<sp<WindowInfoHandle>> touchedSpies = findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus); for (const auto& windowHandle : touchedSpies) { const sp<Connection> connection = getConnectionLocked(windowHandle->getToken()); if (connection != nullptr && connection->responsive) { // This monitor could take more input. Drop all events preceding this // event, so that gesture monitor could get a chance to receive the stream // This spy window could take more input. Drop all events preceding this // event, so that the spy window can get a chance to receive the stream. ALOGW("Pruning the input queue because %s is unresponsive, but we have a " "responsive gesture monitor that may handle the event", "responsive spy window that may handle the event.", mAwaitedFocusedApplication->getName().c_str()); return true; } Loading Loading @@ -2104,6 +2091,13 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle); } if (newTouchedWindows.empty()) { ALOGI("Dropping event because there is no touchable window at (%d, %d) on display %d.", x, y, displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { const WindowInfo& info = *windowHandle->getInfo(); Loading Loading @@ -2172,23 +2166,6 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds); } const std::vector<Monitor> newGestureMonitors = isDown ? selectResponsiveMonitorsLocked( getValueByKey(mGestureMonitorsByDisplay, displayId)) : std::vector<Monitor>{}; if (newTouchedWindows.empty() && newGestureMonitors.empty() && tempTouchState.gestureMonitors.empty()) { ALOGI("Dropping event because there is no touchable window or gesture monitor at " "(%d, %d) in display %" PRId32 ".", x, y, displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } tempTouchState.addGestureMonitors(newGestureMonitors); } else { /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */ Loading Loading @@ -2290,39 +2267,33 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } // Check permission to inject into all touched foreground windows and ensure there // is at least one touched foreground window. { bool haveForegroundOrSpyWindow = false; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { const bool isForeground = (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0; if (touchedWindow.windowHandle->getInfo()->isSpy()) { haveForegroundOrSpyWindow = true; LOG_ALWAYS_FATAL_IF(isForeground, "Spy window cannot be dispatched as a foreground window."); } if (isForeground) { haveForegroundOrSpyWindow = true; if (!checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState)) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; } } } bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); if (!haveForegroundOrSpyWindow && !hasGestureMonitor) { ALOGI("Dropping event because there is no touched window in display " "%" PRId32 " or gesture monitor to receive it.", // Ensure that we have at least one foreground or spy window. It's possible that we dropped some // of the touched windows we previously found if they became paused or unresponsive or were // removed. if (std::none_of(tempTouchState.windows.begin(), tempTouchState.windows.end(), [](const TouchedWindow& touchedWindow) { return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 || touchedWindow.windowHandle->getInfo()->isSpy(); })) { ALOGI("Dropping event because there is no touched window on display %d to receive it.", displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } // Permission granted to injection into all touched foreground windows. injectionPermission = INJECTION_PERMISSION_GRANTED; // Check permission to inject into all touched foreground windows. if (std::any_of(tempTouchState.windows.begin(), tempTouchState.windows.end(), [this, &entry](const TouchedWindow& touchedWindow) { return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 && !checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState); })) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; } // Permission granted to inject into all touched foreground windows. injectionPermission = INJECTION_PERMISSION_GRANTED; // Check whether windows listening for outside touches are owned by the same UID. If it is // set the policy flag that we will not reveal coordinate information to this window. Loading Loading @@ -2380,10 +2351,6 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( touchedWindow.pointerIds, inputTargets); } for (const auto& monitor : tempTouchState.gestureMonitors) { addMonitoringTargetLocked(monitor, displayId, inputTargets); } // Drop the outside or hover touch windows since we will not care about them // in the next iteration. tempTouchState.filterNonAsIsTouchWindows(); Loading Loading @@ -2584,31 +2551,20 @@ void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHa void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId) { std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it = mGlobalMonitorsByDisplay.find(displayId); auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId); if (monitorsIt == mGlobalMonitorsByDisplay.end()) return; if (it != mGlobalMonitorsByDisplay.end()) { const std::vector<Monitor>& monitors = it->second; for (const Monitor& monitor : monitors) { addMonitoringTargetLocked(monitor, displayId, inputTargets); } } } void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId, std::vector<InputTarget>& inputTargets) { for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) { InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; ui::Transform t; if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { const auto& displayTransform = it->second.transform; target.displayTransform = displayTransform; t = displayTransform; target.displayTransform = it->second.transform; } target.setDefaultPointerTransform(t); target.setDefaultPointerTransform(target.displayTransform); inputTargets.push_back(target); } } bool InputDispatcher::checkInjectionPermission(const sp<WindowInfoHandle>& windowHandle, const InjectionState* injectionState) { Loading Loading @@ -3573,15 +3529,7 @@ void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options) { synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay); synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay); } void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) { for (const Monitor& monitor : monitors) { synthesizeCancelationEventsForInputChannelLocked(monitor.inputChannel, options); } Loading Loading @@ -5266,22 +5214,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "Displays: <none>\n"; } if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) { for (auto& it : mGlobalMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first); dumpMonitors(dump, monitors); } for (auto& it : mGestureMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first); if (!mGlobalMonitorsByDisplay.empty()) { for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) { dump += StringPrintf(INDENT "Global monitors on display %d:\n", displayId); dumpMonitors(dump, monitors); } } else { dump += INDENT "Monitors: <none>\n"; dump += INDENT "Global Monitors: <none>\n"; } nsecs_t currentTime = now(); const nsecs_t currentTime = now(); // Dump recently dispatched or dropped events from oldest to newest. if (!mRecentQueue.empty()) { Loading Loading @@ -5439,7 +5381,6 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const } Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_t displayId, bool isGestureMonitor, const std::string& name, int32_t pid) { std::shared_ptr<InputChannel> serverChannel; Loading Loading @@ -5468,13 +5409,9 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_ std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); auto& monitorsByDisplay = isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; monitorsByDisplay[displayId].emplace_back(serverChannel, pid); mGlobalMonitorsByDisplay[displayId].emplace_back(serverChannel, pid); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); ALOGI("Created monitor %s for display %" PRId32 ", gesture=%s, pid=%" PRId32, name.c_str(), displayId, toString(isGestureMonitor), pid); } // Wake the looper because some connections have changed. Loading Loading @@ -5522,26 +5459,14 @@ status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connection } void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) { removeMonitorChannelLocked(connectionToken, mGlobalMonitorsByDisplay); removeMonitorChannelLocked(connectionToken, mGestureMonitorsByDisplay); } for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) { auto& [displayId, monitors] = *it; std::erase_if(monitors, [connectionToken](const Monitor& monitor) { return monitor.inputChannel->getConnectionToken() == connectionToken; }); void InputDispatcher::removeMonitorChannelLocked( const sp<IBinder>& connectionToken, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) { for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) { std::vector<Monitor>& monitors = it->second; const size_t numMonitors = monitors.size(); for (size_t i = 0; i < numMonitors; i++) { if (monitors[i].inputChannel->getConnectionToken() == connectionToken) { ALOGI("Erasing monitor %s on display %" PRId32 ", pid=%" PRId32, monitors[i].inputChannel->getName().c_str(), it->first, monitors[i].pid); monitors.erase(monitors.begin() + i); break; } } if (monitors.empty()) { it = monitorsByDisplay.erase(it); it = mGlobalMonitorsByDisplay.erase(it); } else { ++it; } Loading @@ -5549,66 +5474,31 @@ void InputDispatcher::removeMonitorChannelLocked( } status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { { // acquire lock std::scoped_lock _l(mLock); TouchState* statePtr = nullptr; std::shared_ptr<InputChannel> requestingChannel; int32_t displayId; int32_t deviceId; const std::optional<int32_t> foundGestureMonitorDisplayId = findGestureMonitorDisplayByTokenLocked(token); // TODO: Optimize this function for pilfering from windows when removing gesture monitors. if (foundGestureMonitorDisplayId) { // A gesture monitor has requested to pilfer pointers. displayId = *foundGestureMonitorDisplayId; auto stateIt = mTouchStatesByDisplay.find(displayId); if (stateIt == mTouchStatesByDisplay.end()) { ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); return BAD_VALUE; } statePtr = &stateIt->second; for (const auto& monitor : statePtr->gestureMonitors) { if (monitor.inputChannel->getConnectionToken() == token) { requestingChannel = monitor.inputChannel; deviceId = statePtr->deviceId; } } } else { // Check if a window has requested to pilfer pointers. for (auto& [curDisplayId, state] : mTouchStatesByDisplay) { const sp<WindowInfoHandle>& windowHandle = state.getWindow(token); if (windowHandle != nullptr) { displayId = curDisplayId; requestingChannel = getInputChannelLocked(token); deviceId = state.deviceId; statePtr = &state; break; } } } if (requestingChannel == nullptr) { const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); if (!requestingChannel) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); return BAD_VALUE; } TouchState& state = *statePtr; if (!state.down) { auto [statePtr, windowPtr] = findTouchStateAndWindowLocked(token); if (statePtr == nullptr || windowPtr == nullptr || !statePtr->down) { ALOGW("Attempted to pilfer points from a channel without any on-going pointer streams." " Ignoring."); return BAD_VALUE; } TouchState& state = *statePtr; // Send cancel events to all the input channels we're stealing from. CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "input channel stole pointer stream"); options.deviceId = deviceId; options.displayId = displayId; options.deviceId = state.deviceId; options.displayId = state.displayId; std::string canceledWindows; for (const TouchedWindow& window : state.windows) { std::shared_ptr<InputChannel> channel = const std::shared_ptr<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken()); if (channel != nullptr && channel->getConnectionToken() != token) { synthesizeCancelationEventsForInputChannelLocked(channel, options); Loading @@ -5623,7 +5513,6 @@ status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { // Then clear the current touch state so we stop dispatching to them as well. state.split = false; state.filterWindowsExcept(token); } return OK; } Loading Loading @@ -5677,27 +5566,17 @@ void InputDispatcher::setDisplayEligibilityForPointerCapture(int32_t displayId, } // release lock } std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked( const sp<IBinder>& token) { for (const auto& it : mGestureMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) { for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return it.first; return monitor.pid; } } } return std::nullopt; } std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { std::optional<int32_t> gesturePid = findMonitorPidByToken(mGestureMonitorsByDisplay, token); if (gesturePid.has_value()) { return gesturePid; } return findMonitorPidByToken(mGlobalMonitorsByDisplay, token); } sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { if (inputConnectionToken == nullptr) { return nullptr; Loading services/inputflinger/dispatcher/InputDispatcher.h +0 −19 Original line number Diff line number Diff line Loading @@ -129,7 +129,6 @@ public: const std::string& name) override; void setFocusedWindow(const android::gui::FocusRequest&) override; base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId, bool isGestureMonitor, const std::string& name, int32_t pid) override; status_t removeInputChannel(const sp<IBinder>& connectionToken) override; Loading Loading @@ -260,21 +259,12 @@ private: std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Find a monitor pid by the provided token. std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Input channels that will receive a copy of all input events sent to the provided display. std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); // Input channels that will receive pointer events that start within the corresponding display. // These are a bit special when compared to global monitors since they'll cause gesture streams // to continue even when there isn't a touched window,and have the ability to steal the rest of // the pointer stream in order to claim it for a system gesture. std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock); const HmacKeyManager mHmacKeyManager; const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const; Loading Loading @@ -530,7 +520,6 @@ private: sp<android::gui::WindowInfoHandle> mLastHoverWindowHandle GUARDED_BY(mLock); void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) 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. // This also means that we will miss cases like pulling down notification shade when the Loading @@ -551,8 +540,6 @@ private: void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId, std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); Loading Loading @@ -618,9 +605,6 @@ private: REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock); void synthesizeCancelationEventsForInputChannelLocked( const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) REQUIRES(mLock); Loading @@ -646,9 +630,6 @@ private: // Registration. void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock); void removeMonitorChannelLocked( const sp<IBinder>& connectionToken, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock); status_t removeInputChannelLocked(const sp<IBinder>& connectionToken, bool notify) REQUIRES(mLock); Loading services/inputflinger/dispatcher/TouchState.cpp +0 −9 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ void TouchState::reset() { source = 0; displayId = ADISPLAY_ID_NONE; windows.clear(); gestureMonitors.clear(); } void TouchState::copyFrom(const TouchState& other) { Loading @@ -47,7 +46,6 @@ void TouchState::copyFrom(const TouchState& other) { source = other.source; displayId = other.displayId; windows = other.windows; gestureMonitors = other.gestureMonitors; } void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags, Loading Loading @@ -75,13 +73,6 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int windows.push_back(touchedWindow); } void TouchState::addGestureMonitors(const std::vector<Monitor>& newMonitors) { const size_t newSize = gestureMonitors.size() + newMonitors.size(); gestureMonitors.reserve(newSize); gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors), std::end(newMonitors)); } void TouchState::removeWindowByToken(const sp<IBinder>& token) { for (size_t i = 0; i < windows.size(); i++) { if (windows[i].windowHandle->getToken() == token) { Loading services/inputflinger/dispatcher/TouchState.h +0 −3 Original line number Diff line number Diff line Loading @@ -36,15 +36,12 @@ struct TouchState { int32_t displayId; // id to the display that currently has a touch, others are rejected std::vector<TouchedWindow> windows; std::vector<Monitor> gestureMonitors; TouchState(); ~TouchState(); void reset(); void copyFrom(const TouchState& other); void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds); void addGestureMonitors(const std::vector<Monitor>& monitors); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); void filterWindowsExcept(const sp<IBinder>& token); Loading services/inputflinger/dispatcher/include/InputDispatcherInterface.h +2 −4 Original line number Diff line number Diff line Loading @@ -169,16 +169,14 @@ public: const std::string& name) = 0; /** * Creates an input channel to be used to monitor input events. * Creates an input channel to be used to monitor all input events on a display. * * Each monitor must target a specific display and will only receive input events sent to that * display. If the monitor is a gesture monitor, it will only receive pointer events on the * targeted display. * display. * * This method may be called on any thread (usually by the input manager). */ virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId, bool gestureMonitor, const std::string& name, int32_t pid) = 0; Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +100 −221 Original line number Diff line number Diff line Loading @@ -417,20 +417,6 @@ KeyEvent createKeyEvent(const KeyEntry& entry) { return event; } std::optional<int32_t> findMonitorPidByToken( const std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay, const sp<IBinder>& token) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return monitor.pid; } } } return std::nullopt; } bool shouldReportMetricsForConnection(const Connection& connection) { // Do not keep track of gesture monitors. They receive every event and would disproportionately // affect the statistics. Loading Loading @@ -948,15 +934,16 @@ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEnt return true; } // Alternatively, maybe there's a gesture monitor that could handle this event for (const auto& monitor : getValueByKey(mGestureMonitorsByDisplay, displayId)) { sp<Connection> connection = getConnectionLocked(monitor.inputChannel->getConnectionToken()); // Alternatively, maybe there's a spy window that could handle this event. const std::vector<sp<WindowInfoHandle>> touchedSpies = findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus); for (const auto& windowHandle : touchedSpies) { const sp<Connection> connection = getConnectionLocked(windowHandle->getToken()); if (connection != nullptr && connection->responsive) { // This monitor could take more input. Drop all events preceding this // event, so that gesture monitor could get a chance to receive the stream // This spy window could take more input. Drop all events preceding this // event, so that the spy window can get a chance to receive the stream. ALOGW("Pruning the input queue because %s is unresponsive, but we have a " "responsive gesture monitor that may handle the event", "responsive spy window that may handle the event.", mAwaitedFocusedApplication->getName().c_str()); return true; } Loading Loading @@ -2104,6 +2091,13 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle); } if (newTouchedWindows.empty()) { ALOGI("Dropping event because there is no touchable window at (%d, %d) on display %d.", x, y, displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { const WindowInfo& info = *windowHandle->getInfo(); Loading Loading @@ -2172,23 +2166,6 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds); } const std::vector<Monitor> newGestureMonitors = isDown ? selectResponsiveMonitorsLocked( getValueByKey(mGestureMonitorsByDisplay, displayId)) : std::vector<Monitor>{}; if (newTouchedWindows.empty() && newGestureMonitors.empty() && tempTouchState.gestureMonitors.empty()) { ALOGI("Dropping event because there is no touchable window or gesture monitor at " "(%d, %d) in display %" PRId32 ".", x, y, displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } tempTouchState.addGestureMonitors(newGestureMonitors); } else { /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */ Loading Loading @@ -2290,39 +2267,33 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } // Check permission to inject into all touched foreground windows and ensure there // is at least one touched foreground window. { bool haveForegroundOrSpyWindow = false; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { const bool isForeground = (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0; if (touchedWindow.windowHandle->getInfo()->isSpy()) { haveForegroundOrSpyWindow = true; LOG_ALWAYS_FATAL_IF(isForeground, "Spy window cannot be dispatched as a foreground window."); } if (isForeground) { haveForegroundOrSpyWindow = true; if (!checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState)) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; } } } bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); if (!haveForegroundOrSpyWindow && !hasGestureMonitor) { ALOGI("Dropping event because there is no touched window in display " "%" PRId32 " or gesture monitor to receive it.", // Ensure that we have at least one foreground or spy window. It's possible that we dropped some // of the touched windows we previously found if they became paused or unresponsive or were // removed. if (std::none_of(tempTouchState.windows.begin(), tempTouchState.windows.end(), [](const TouchedWindow& touchedWindow) { return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 || touchedWindow.windowHandle->getInfo()->isSpy(); })) { ALOGI("Dropping event because there is no touched window on display %d to receive it.", displayId); injectionResult = InputEventInjectionResult::FAILED; goto Failed; } // Permission granted to injection into all touched foreground windows. injectionPermission = INJECTION_PERMISSION_GRANTED; // Check permission to inject into all touched foreground windows. if (std::any_of(tempTouchState.windows.begin(), tempTouchState.windows.end(), [this, &entry](const TouchedWindow& touchedWindow) { return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 && !checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState); })) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; } // Permission granted to inject into all touched foreground windows. injectionPermission = INJECTION_PERMISSION_GRANTED; // Check whether windows listening for outside touches are owned by the same UID. If it is // set the policy flag that we will not reveal coordinate information to this window. Loading Loading @@ -2380,10 +2351,6 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( touchedWindow.pointerIds, inputTargets); } for (const auto& monitor : tempTouchState.gestureMonitors) { addMonitoringTargetLocked(monitor, displayId, inputTargets); } // Drop the outside or hover touch windows since we will not care about them // in the next iteration. tempTouchState.filterNonAsIsTouchWindows(); Loading Loading @@ -2584,31 +2551,20 @@ void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHa void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId) { std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it = mGlobalMonitorsByDisplay.find(displayId); auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId); if (monitorsIt == mGlobalMonitorsByDisplay.end()) return; if (it != mGlobalMonitorsByDisplay.end()) { const std::vector<Monitor>& monitors = it->second; for (const Monitor& monitor : monitors) { addMonitoringTargetLocked(monitor, displayId, inputTargets); } } } void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId, std::vector<InputTarget>& inputTargets) { for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) { InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; ui::Transform t; if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { const auto& displayTransform = it->second.transform; target.displayTransform = displayTransform; t = displayTransform; target.displayTransform = it->second.transform; } target.setDefaultPointerTransform(t); target.setDefaultPointerTransform(target.displayTransform); inputTargets.push_back(target); } } bool InputDispatcher::checkInjectionPermission(const sp<WindowInfoHandle>& windowHandle, const InjectionState* injectionState) { Loading Loading @@ -3573,15 +3529,7 @@ void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options) { synthesizeCancelationEventsForMonitorsLocked(options, mGlobalMonitorsByDisplay); synthesizeCancelationEventsForMonitorsLocked(options, mGestureMonitorsByDisplay); } void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) { for (const Monitor& monitor : monitors) { synthesizeCancelationEventsForInputChannelLocked(monitor.inputChannel, options); } Loading Loading @@ -5266,22 +5214,16 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "Displays: <none>\n"; } if (!mGlobalMonitorsByDisplay.empty() || !mGestureMonitorsByDisplay.empty()) { for (auto& it : mGlobalMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; dump += StringPrintf(INDENT "Global monitors in display %" PRId32 ":\n", it.first); dumpMonitors(dump, monitors); } for (auto& it : mGestureMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; dump += StringPrintf(INDENT "Gesture monitors in display %" PRId32 ":\n", it.first); if (!mGlobalMonitorsByDisplay.empty()) { for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) { dump += StringPrintf(INDENT "Global monitors on display %d:\n", displayId); dumpMonitors(dump, monitors); } } else { dump += INDENT "Monitors: <none>\n"; dump += INDENT "Global Monitors: <none>\n"; } nsecs_t currentTime = now(); const nsecs_t currentTime = now(); // Dump recently dispatched or dropped events from oldest to newest. if (!mRecentQueue.empty()) { Loading Loading @@ -5439,7 +5381,6 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const } Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_t displayId, bool isGestureMonitor, const std::string& name, int32_t pid) { std::shared_ptr<InputChannel> serverChannel; Loading Loading @@ -5468,13 +5409,9 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_ std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); auto& monitorsByDisplay = isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; monitorsByDisplay[displayId].emplace_back(serverChannel, pid); mGlobalMonitorsByDisplay[displayId].emplace_back(serverChannel, pid); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); ALOGI("Created monitor %s for display %" PRId32 ", gesture=%s, pid=%" PRId32, name.c_str(), displayId, toString(isGestureMonitor), pid); } // Wake the looper because some connections have changed. Loading Loading @@ -5522,26 +5459,14 @@ status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connection } void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) { removeMonitorChannelLocked(connectionToken, mGlobalMonitorsByDisplay); removeMonitorChannelLocked(connectionToken, mGestureMonitorsByDisplay); } for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) { auto& [displayId, monitors] = *it; std::erase_if(monitors, [connectionToken](const Monitor& monitor) { return monitor.inputChannel->getConnectionToken() == connectionToken; }); void InputDispatcher::removeMonitorChannelLocked( const sp<IBinder>& connectionToken, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) { for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) { std::vector<Monitor>& monitors = it->second; const size_t numMonitors = monitors.size(); for (size_t i = 0; i < numMonitors; i++) { if (monitors[i].inputChannel->getConnectionToken() == connectionToken) { ALOGI("Erasing monitor %s on display %" PRId32 ", pid=%" PRId32, monitors[i].inputChannel->getName().c_str(), it->first, monitors[i].pid); monitors.erase(monitors.begin() + i); break; } } if (monitors.empty()) { it = monitorsByDisplay.erase(it); it = mGlobalMonitorsByDisplay.erase(it); } else { ++it; } Loading @@ -5549,66 +5474,31 @@ void InputDispatcher::removeMonitorChannelLocked( } status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { { // acquire lock std::scoped_lock _l(mLock); TouchState* statePtr = nullptr; std::shared_ptr<InputChannel> requestingChannel; int32_t displayId; int32_t deviceId; const std::optional<int32_t> foundGestureMonitorDisplayId = findGestureMonitorDisplayByTokenLocked(token); // TODO: Optimize this function for pilfering from windows when removing gesture monitors. if (foundGestureMonitorDisplayId) { // A gesture monitor has requested to pilfer pointers. displayId = *foundGestureMonitorDisplayId; auto stateIt = mTouchStatesByDisplay.find(displayId); if (stateIt == mTouchStatesByDisplay.end()) { ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); return BAD_VALUE; } statePtr = &stateIt->second; for (const auto& monitor : statePtr->gestureMonitors) { if (monitor.inputChannel->getConnectionToken() == token) { requestingChannel = monitor.inputChannel; deviceId = statePtr->deviceId; } } } else { // Check if a window has requested to pilfer pointers. for (auto& [curDisplayId, state] : mTouchStatesByDisplay) { const sp<WindowInfoHandle>& windowHandle = state.getWindow(token); if (windowHandle != nullptr) { displayId = curDisplayId; requestingChannel = getInputChannelLocked(token); deviceId = state.deviceId; statePtr = &state; break; } } } if (requestingChannel == nullptr) { const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token); if (!requestingChannel) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); return BAD_VALUE; } TouchState& state = *statePtr; if (!state.down) { auto [statePtr, windowPtr] = findTouchStateAndWindowLocked(token); if (statePtr == nullptr || windowPtr == nullptr || !statePtr->down) { ALOGW("Attempted to pilfer points from a channel without any on-going pointer streams." " Ignoring."); return BAD_VALUE; } TouchState& state = *statePtr; // Send cancel events to all the input channels we're stealing from. CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "input channel stole pointer stream"); options.deviceId = deviceId; options.displayId = displayId; options.deviceId = state.deviceId; options.displayId = state.displayId; std::string canceledWindows; for (const TouchedWindow& window : state.windows) { std::shared_ptr<InputChannel> channel = const std::shared_ptr<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken()); if (channel != nullptr && channel->getConnectionToken() != token) { synthesizeCancelationEventsForInputChannelLocked(channel, options); Loading @@ -5623,7 +5513,6 @@ status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { // Then clear the current touch state so we stop dispatching to them as well. state.split = false; state.filterWindowsExcept(token); } return OK; } Loading Loading @@ -5677,27 +5566,17 @@ void InputDispatcher::setDisplayEligibilityForPointerCapture(int32_t displayId, } // release lock } std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked( const sp<IBinder>& token) { for (const auto& it : mGestureMonitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) { for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return it.first; return monitor.pid; } } } return std::nullopt; } std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { std::optional<int32_t> gesturePid = findMonitorPidByToken(mGestureMonitorsByDisplay, token); if (gesturePid.has_value()) { return gesturePid; } return findMonitorPidByToken(mGlobalMonitorsByDisplay, token); } sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { if (inputConnectionToken == nullptr) { return nullptr; Loading
services/inputflinger/dispatcher/InputDispatcher.h +0 −19 Original line number Diff line number Diff line Loading @@ -129,7 +129,6 @@ public: const std::string& name) override; void setFocusedWindow(const android::gui::FocusRequest&) override; base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId, bool isGestureMonitor, const std::string& name, int32_t pid) override; status_t removeInputChannel(const sp<IBinder>& connectionToken) override; Loading Loading @@ -260,21 +259,12 @@ private: std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Find a monitor pid by the provided token. std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Input channels that will receive a copy of all input events sent to the provided display. std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); // Input channels that will receive pointer events that start within the corresponding display. // These are a bit special when compared to global monitors since they'll cause gesture streams // to continue even when there isn't a touched window,and have the ability to steal the rest of // the pointer stream in order to claim it for a system gesture. std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock); const HmacKeyManager mHmacKeyManager; const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const; Loading Loading @@ -530,7 +520,6 @@ private: sp<android::gui::WindowInfoHandle> mLastHoverWindowHandle GUARDED_BY(mLock); void cancelEventsForAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) 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. // This also means that we will miss cases like pulling down notification shade when the Loading @@ -551,8 +540,6 @@ private: void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId, std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); Loading Loading @@ -618,9 +605,6 @@ private: REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock); void synthesizeCancelationEventsForInputChannelLocked( const std::shared_ptr<InputChannel>& channel, const CancelationOptions& options) REQUIRES(mLock); Loading @@ -646,9 +630,6 @@ private: // Registration. void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock); void removeMonitorChannelLocked( const sp<IBinder>& connectionToken, std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock); status_t removeInputChannelLocked(const sp<IBinder>& connectionToken, bool notify) REQUIRES(mLock); Loading
services/inputflinger/dispatcher/TouchState.cpp +0 −9 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ void TouchState::reset() { source = 0; displayId = ADISPLAY_ID_NONE; windows.clear(); gestureMonitors.clear(); } void TouchState::copyFrom(const TouchState& other) { Loading @@ -47,7 +46,6 @@ void TouchState::copyFrom(const TouchState& other) { source = other.source; displayId = other.displayId; windows = other.windows; gestureMonitors = other.gestureMonitors; } void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags, Loading Loading @@ -75,13 +73,6 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int windows.push_back(touchedWindow); } void TouchState::addGestureMonitors(const std::vector<Monitor>& newMonitors) { const size_t newSize = gestureMonitors.size() + newMonitors.size(); gestureMonitors.reserve(newSize); gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors), std::end(newMonitors)); } void TouchState::removeWindowByToken(const sp<IBinder>& token) { for (size_t i = 0; i < windows.size(); i++) { if (windows[i].windowHandle->getToken() == token) { Loading
services/inputflinger/dispatcher/TouchState.h +0 −3 Original line number Diff line number Diff line Loading @@ -36,15 +36,12 @@ struct TouchState { int32_t displayId; // id to the display that currently has a touch, others are rejected std::vector<TouchedWindow> windows; std::vector<Monitor> gestureMonitors; TouchState(); ~TouchState(); void reset(); void copyFrom(const TouchState& other); void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds); void addGestureMonitors(const std::vector<Monitor>& monitors); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); void filterWindowsExcept(const sp<IBinder>& token); Loading
services/inputflinger/dispatcher/include/InputDispatcherInterface.h +2 −4 Original line number Diff line number Diff line Loading @@ -169,16 +169,14 @@ public: const std::string& name) = 0; /** * Creates an input channel to be used to monitor input events. * Creates an input channel to be used to monitor all input events on a display. * * Each monitor must target a specific display and will only receive input events sent to that * display. If the monitor is a gesture monitor, it will only receive pointer events on the * targeted display. * display. * * This method may be called on any thread (usually by the input manager). */ virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId, bool gestureMonitor, const std::string& name, int32_t pid) = 0; Loading