Loading libs/gui/WindowInfo.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,10 @@ bool WindowInfo::supportsSplitTouch() const { return flags.test(Flag::SPLIT_TOUCH); return flags.test(Flag::SPLIT_TOUCH); } } bool WindowInfo::isSpy() const { return inputFeatures.test(Feature::SPY); } bool WindowInfo::overlaps(const WindowInfo* other) const { bool WindowInfo::overlaps(const WindowInfo* other) const { return frameLeft < other->frameRight && frameRight > other->frameLeft && return frameLeft < other->frameRight && frameRight > other->frameLeft && frameTop < other->frameBottom && frameBottom > other->frameTop; frameTop < other->frameBottom && frameBottom > other->frameTop; Loading libs/gui/include/gui/WindowInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -137,6 +137,7 @@ struct WindowInfo : public Parcelable { DISABLE_USER_ACTIVITY = 1u << 2, DISABLE_USER_ACTIVITY = 1u << 2, DROP_INPUT = 1u << 3, DROP_INPUT = 1u << 3, DROP_INPUT_IF_OBSCURED = 1u << 4, DROP_INPUT_IF_OBSCURED = 1u << 4, SPY = 1u << 5, }; }; /* These values are filled in by the WM and passed through SurfaceFlinger /* These values are filled in by the WM and passed through SurfaceFlinger Loading Loading @@ -215,6 +216,8 @@ struct WindowInfo : public Parcelable { bool supportsSplitTouch() const; bool supportsSplitTouch() const; bool isSpy() const; bool overlaps(const WindowInfo* other) const; bool overlaps(const WindowInfo* other) const; bool operator==(const WindowInfo& inputChannel) const; bool operator==(const WindowInfo& inputChannel) const; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +92 −40 Original line number Original line Diff line number Diff line Loading @@ -1051,14 +1051,14 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayI LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets"); LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets"); } } // Traverse windows from front to back to find touched window. // Traverse windows from front to back to find touched window. const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); const auto& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { continue; continue; } } const WindowInfo& info = *windowHandle->getInfo(); const WindowInfo& info = *windowHandle->getInfo(); if (windowAcceptsTouchAt(info, displayId, x, y)) { if (!info.isSpy() && windowAcceptsTouchAt(info, displayId, x, y)) { return windowHandle; return windowHandle; } } Loading @@ -1070,6 +1070,27 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayI return nullptr; return nullptr; } } std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(int32_t displayId, int32_t x, int32_t y) const { // Traverse windows from front to back and gather the touched spy windows. std::vector<sp<WindowInfoHandle>> spyWindows; const auto& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { const WindowInfo& info = *windowHandle->getInfo(); if (!windowAcceptsTouchAt(info, displayId, x, y)) { continue; } if (!info.isSpy()) { // The first touched non-spy window was found, so return the spy windows touched so far. return spyWindows; } spyWindows.push_back(windowHandle); } return spyWindows; } void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) { void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) { const char* reason; const char* reason; switch (dropReason) { switch (dropReason) { Loading Loading @@ -2078,9 +2099,11 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } } } std::vector<sp<WindowInfoHandle>> newTouchedWindows; std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAtLocked(displayId, x, y); if (newTouchedWindowHandle != nullptr) { if (newTouchedWindowHandle != nullptr) { newTouchedWindows.push_back(newTouchedWindowHandle); // Process the foreground window first so that it is the first to receive the event. newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle); } } for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { Loading Loading @@ -2128,8 +2151,10 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Set target flags. // Set target flags. int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; if (!info.isSpy()) { // There should only be one new foreground (non-spy) window at this location. // There should only be one new foreground (non-spy) window at this location. targetFlags |= InputTarget::FLAG_FOREGROUND; targetFlags |= InputTarget::FLAG_FOREGROUND; } if (isSplit) { if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; targetFlags |= InputTarget::FLAG_SPLIT; Loading Loading @@ -2268,10 +2293,17 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Check permission to inject into all touched foreground windows and ensure there // Check permission to inject into all touched foreground windows and ensure there // is at least one touched foreground window. // is at least one touched foreground window. { { bool haveForegroundWindow = false; bool haveForegroundOrSpyWindow = false; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { for (const TouchedWindow& touchedWindow : tempTouchState.windows) { if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { const bool isForeground = haveForegroundWindow = true; (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)) { if (!checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState)) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; Loading @@ -2280,8 +2312,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } } } bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); if (!haveForegroundWindow && !hasGestureMonitor) { if (!haveForegroundOrSpyWindow && !hasGestureMonitor) { ALOGI("Dropping event because there is no touched foreground window in display " ALOGI("Dropping event because there is no touched window in display " "%" PRId32 " or gesture monitor to receive it.", "%" PRId32 " or gesture monitor to receive it.", displayId); displayId); injectionResult = InputEventInjectionResult::FAILED; injectionResult = InputEventInjectionResult::FAILED; Loading Loading @@ -5521,58 +5553,78 @@ void InputDispatcher::removeMonitorChannelLocked( status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { { // acquire lock { // acquire lock std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); std::optional<int32_t> foundDisplayId = findGestureMonitorDisplayByTokenLocked(token); if (!foundDisplayId) { TouchState* statePtr = nullptr; ALOGW("Attempted to pilfer pointers from an un-registered monitor or invalid token"); std::shared_ptr<InputChannel> requestingChannel; return BAD_VALUE; int32_t displayId; } int32_t deviceId; int32_t displayId = foundDisplayId.value(); const std::optional<int32_t> foundGestureMonitorDisplayId = findGestureMonitorDisplayByTokenLocked(token); std::unordered_map<int32_t, TouchState>::iterator stateIt = mTouchStatesByDisplay.find(displayId); // 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()) { if (stateIt == mTouchStatesByDisplay.end()) { ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); return BAD_VALUE; return BAD_VALUE; } } statePtr = &stateIt->second; TouchState& state = stateIt->second; for (const auto& monitor : statePtr->gestureMonitors) { std::shared_ptr<InputChannel> requestingChannel; std::optional<int32_t> foundDeviceId; for (const auto& monitor : state.gestureMonitors) { if (monitor.inputChannel->getConnectionToken() == token) { if (monitor.inputChannel->getConnectionToken() == token) { requestingChannel = monitor.inputChannel; requestingChannel = monitor.inputChannel; foundDeviceId = state.deviceId; 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 (!foundDeviceId || !state.down) { ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams." if (requestingChannel == nullptr) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); return BAD_VALUE; } TouchState& state = *statePtr; if (!state.down) { ALOGW("Attempted to pilfer points from a channel without any on-going pointer streams." " Ignoring."); " Ignoring."); return BAD_VALUE; return BAD_VALUE; } } int32_t deviceId = foundDeviceId.value(); // Send cancel events to all the input channels we're stealing from. // Send cancel events to all the input channels we're stealing from. CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "gesture monitor stole pointer stream"); "input channel stole pointer stream"); options.deviceId = deviceId; options.deviceId = deviceId; options.displayId = displayId; options.displayId = displayId; std::string canceledWindows = "["; std::string canceledWindows; for (const TouchedWindow& window : state.windows) { for (const TouchedWindow& window : state.windows) { std::shared_ptr<InputChannel> channel = std::shared_ptr<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken()); getInputChannelLocked(window.windowHandle->getToken()); if (channel != nullptr) { if (channel != nullptr && channel->getConnectionToken() != token) { synthesizeCancelationEventsForInputChannelLocked(channel, options); synthesizeCancelationEventsForInputChannelLocked(channel, options); canceledWindows += channel->getName() + ", "; canceledWindows += canceledWindows.empty() ? "[" : ", "; canceledWindows += channel->getName(); } } } } canceledWindows += "]"; canceledWindows += canceledWindows.empty() ? "[]" : "]"; ALOGI("Monitor %s is stealing touch from %s", requestingChannel->getName().c_str(), ALOGI("Channel %s is stealing touch from %s", requestingChannel->getName().c_str(), canceledWindows.c_str()); canceledWindows.c_str()); // Then clear the current touch state so we stop dispatching to them as well. // Then clear the current touch state so we stop dispatching to them as well. state.split = false; state.split = false; state.filterNonMonitors(); state.filterWindowsExcept(token); } } return OK; return OK; } } Loading services/inputflinger/dispatcher/InputDispatcher.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -240,6 +240,11 @@ private: bool ignoreDragWindow = false) bool ignoreDragWindow = false) REQUIRES(mLock); REQUIRES(mLock); std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(int32_t displayId, int32_t x, int32_t y) const REQUIRES(mLock); sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const REQUIRES(mLock); REQUIRES(mLock); Loading services/inputflinger/dispatcher/TouchState.cpp +15 −2 Original line number Original line Diff line number Diff line Loading @@ -105,8 +105,11 @@ void TouchState::filterNonAsIsTouchWindows() { } } } } void TouchState::filterNonMonitors() { void TouchState::filterWindowsExcept(const sp<IBinder>& token) { windows.clear(); auto it = std::remove_if(windows.begin(), windows.end(), [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; }); windows.erase(it, windows.end()); } } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { Loading Loading @@ -144,4 +147,14 @@ sp<WindowInfoHandle> TouchState::getWallpaperWindow() const { return nullptr; return nullptr; } } sp<WindowInfoHandle> TouchState::getWindow(const sp<IBinder>& token) const { for (const TouchedWindow& touchedWindow : windows) { const auto& windowHandle = touchedWindow.windowHandle; if (windowHandle->getToken() == token) { return windowHandle; } } return nullptr; } } // namespace android::inputdispatcher } // namespace android::inputdispatcher Loading
libs/gui/WindowInfo.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,10 @@ bool WindowInfo::supportsSplitTouch() const { return flags.test(Flag::SPLIT_TOUCH); return flags.test(Flag::SPLIT_TOUCH); } } bool WindowInfo::isSpy() const { return inputFeatures.test(Feature::SPY); } bool WindowInfo::overlaps(const WindowInfo* other) const { bool WindowInfo::overlaps(const WindowInfo* other) const { return frameLeft < other->frameRight && frameRight > other->frameLeft && return frameLeft < other->frameRight && frameRight > other->frameLeft && frameTop < other->frameBottom && frameBottom > other->frameTop; frameTop < other->frameBottom && frameBottom > other->frameTop; Loading
libs/gui/include/gui/WindowInfo.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -137,6 +137,7 @@ struct WindowInfo : public Parcelable { DISABLE_USER_ACTIVITY = 1u << 2, DISABLE_USER_ACTIVITY = 1u << 2, DROP_INPUT = 1u << 3, DROP_INPUT = 1u << 3, DROP_INPUT_IF_OBSCURED = 1u << 4, DROP_INPUT_IF_OBSCURED = 1u << 4, SPY = 1u << 5, }; }; /* These values are filled in by the WM and passed through SurfaceFlinger /* These values are filled in by the WM and passed through SurfaceFlinger Loading Loading @@ -215,6 +216,8 @@ struct WindowInfo : public Parcelable { bool supportsSplitTouch() const; bool supportsSplitTouch() const; bool isSpy() const; bool overlaps(const WindowInfo* other) const; bool overlaps(const WindowInfo* other) const; bool operator==(const WindowInfo& inputChannel) const; bool operator==(const WindowInfo& inputChannel) const; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +92 −40 Original line number Original line Diff line number Diff line Loading @@ -1051,14 +1051,14 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayI LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets"); LOG_ALWAYS_FATAL("Must provide a valid touch state if adding outside targets"); } } // Traverse windows from front to back to find touched window. // Traverse windows from front to back to find touched window. const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); const auto& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { continue; continue; } } const WindowInfo& info = *windowHandle->getInfo(); const WindowInfo& info = *windowHandle->getInfo(); if (windowAcceptsTouchAt(info, displayId, x, y)) { if (!info.isSpy() && windowAcceptsTouchAt(info, displayId, x, y)) { return windowHandle; return windowHandle; } } Loading @@ -1070,6 +1070,27 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayI return nullptr; return nullptr; } } std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(int32_t displayId, int32_t x, int32_t y) const { // Traverse windows from front to back and gather the touched spy windows. std::vector<sp<WindowInfoHandle>> spyWindows; const auto& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { const WindowInfo& info = *windowHandle->getInfo(); if (!windowAcceptsTouchAt(info, displayId, x, y)) { continue; } if (!info.isSpy()) { // The first touched non-spy window was found, so return the spy windows touched so far. return spyWindows; } spyWindows.push_back(windowHandle); } return spyWindows; } void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) { void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) { const char* reason; const char* reason; switch (dropReason) { switch (dropReason) { Loading Loading @@ -2078,9 +2099,11 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } } } std::vector<sp<WindowInfoHandle>> newTouchedWindows; std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAtLocked(displayId, x, y); if (newTouchedWindowHandle != nullptr) { if (newTouchedWindowHandle != nullptr) { newTouchedWindows.push_back(newTouchedWindowHandle); // Process the foreground window first so that it is the first to receive the event. newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle); } } for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) { Loading Loading @@ -2128,8 +2151,10 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Set target flags. // Set target flags. int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; if (!info.isSpy()) { // There should only be one new foreground (non-spy) window at this location. // There should only be one new foreground (non-spy) window at this location. targetFlags |= InputTarget::FLAG_FOREGROUND; targetFlags |= InputTarget::FLAG_FOREGROUND; } if (isSplit) { if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; targetFlags |= InputTarget::FLAG_SPLIT; Loading Loading @@ -2268,10 +2293,17 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Check permission to inject into all touched foreground windows and ensure there // Check permission to inject into all touched foreground windows and ensure there // is at least one touched foreground window. // is at least one touched foreground window. { { bool haveForegroundWindow = false; bool haveForegroundOrSpyWindow = false; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { for (const TouchedWindow& touchedWindow : tempTouchState.windows) { if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { const bool isForeground = haveForegroundWindow = true; (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)) { if (!checkInjectionPermission(touchedWindow.windowHandle, entry.injectionState)) { injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionResult = InputEventInjectionResult::PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; Loading @@ -2280,8 +2312,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } } } } bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); bool hasGestureMonitor = !tempTouchState.gestureMonitors.empty(); if (!haveForegroundWindow && !hasGestureMonitor) { if (!haveForegroundOrSpyWindow && !hasGestureMonitor) { ALOGI("Dropping event because there is no touched foreground window in display " ALOGI("Dropping event because there is no touched window in display " "%" PRId32 " or gesture monitor to receive it.", "%" PRId32 " or gesture monitor to receive it.", displayId); displayId); injectionResult = InputEventInjectionResult::FAILED; injectionResult = InputEventInjectionResult::FAILED; Loading Loading @@ -5521,58 +5553,78 @@ void InputDispatcher::removeMonitorChannelLocked( status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) { { // acquire lock { // acquire lock std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); std::optional<int32_t> foundDisplayId = findGestureMonitorDisplayByTokenLocked(token); if (!foundDisplayId) { TouchState* statePtr = nullptr; ALOGW("Attempted to pilfer pointers from an un-registered monitor or invalid token"); std::shared_ptr<InputChannel> requestingChannel; return BAD_VALUE; int32_t displayId; } int32_t deviceId; int32_t displayId = foundDisplayId.value(); const std::optional<int32_t> foundGestureMonitorDisplayId = findGestureMonitorDisplayByTokenLocked(token); std::unordered_map<int32_t, TouchState>::iterator stateIt = mTouchStatesByDisplay.find(displayId); // 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()) { if (stateIt == mTouchStatesByDisplay.end()) { ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); ALOGW("Failed to pilfer pointers: no pointers on display %" PRId32 ".", displayId); return BAD_VALUE; return BAD_VALUE; } } statePtr = &stateIt->second; TouchState& state = stateIt->second; for (const auto& monitor : statePtr->gestureMonitors) { std::shared_ptr<InputChannel> requestingChannel; std::optional<int32_t> foundDeviceId; for (const auto& monitor : state.gestureMonitors) { if (monitor.inputChannel->getConnectionToken() == token) { if (monitor.inputChannel->getConnectionToken() == token) { requestingChannel = monitor.inputChannel; requestingChannel = monitor.inputChannel; foundDeviceId = state.deviceId; 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 (!foundDeviceId || !state.down) { ALOGW("Attempted to pilfer points from a monitor without any on-going pointer streams." if (requestingChannel == nullptr) { ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token"); return BAD_VALUE; } TouchState& state = *statePtr; if (!state.down) { ALOGW("Attempted to pilfer points from a channel without any on-going pointer streams." " Ignoring."); " Ignoring."); return BAD_VALUE; return BAD_VALUE; } } int32_t deviceId = foundDeviceId.value(); // Send cancel events to all the input channels we're stealing from. // Send cancel events to all the input channels we're stealing from. CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "gesture monitor stole pointer stream"); "input channel stole pointer stream"); options.deviceId = deviceId; options.deviceId = deviceId; options.displayId = displayId; options.displayId = displayId; std::string canceledWindows = "["; std::string canceledWindows; for (const TouchedWindow& window : state.windows) { for (const TouchedWindow& window : state.windows) { std::shared_ptr<InputChannel> channel = std::shared_ptr<InputChannel> channel = getInputChannelLocked(window.windowHandle->getToken()); getInputChannelLocked(window.windowHandle->getToken()); if (channel != nullptr) { if (channel != nullptr && channel->getConnectionToken() != token) { synthesizeCancelationEventsForInputChannelLocked(channel, options); synthesizeCancelationEventsForInputChannelLocked(channel, options); canceledWindows += channel->getName() + ", "; canceledWindows += canceledWindows.empty() ? "[" : ", "; canceledWindows += channel->getName(); } } } } canceledWindows += "]"; canceledWindows += canceledWindows.empty() ? "[]" : "]"; ALOGI("Monitor %s is stealing touch from %s", requestingChannel->getName().c_str(), ALOGI("Channel %s is stealing touch from %s", requestingChannel->getName().c_str(), canceledWindows.c_str()); canceledWindows.c_str()); // Then clear the current touch state so we stop dispatching to them as well. // Then clear the current touch state so we stop dispatching to them as well. state.split = false; state.split = false; state.filterNonMonitors(); state.filterWindowsExcept(token); } } return OK; return OK; } } Loading
services/inputflinger/dispatcher/InputDispatcher.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -240,6 +240,11 @@ private: bool ignoreDragWindow = false) bool ignoreDragWindow = false) REQUIRES(mLock); REQUIRES(mLock); std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(int32_t displayId, int32_t x, int32_t y) const REQUIRES(mLock); sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const REQUIRES(mLock); REQUIRES(mLock); Loading
services/inputflinger/dispatcher/TouchState.cpp +15 −2 Original line number Original line Diff line number Diff line Loading @@ -105,8 +105,11 @@ void TouchState::filterNonAsIsTouchWindows() { } } } } void TouchState::filterNonMonitors() { void TouchState::filterWindowsExcept(const sp<IBinder>& token) { windows.clear(); auto it = std::remove_if(windows.begin(), windows.end(), [&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; }); windows.erase(it, windows.end()); } } sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { Loading Loading @@ -144,4 +147,14 @@ sp<WindowInfoHandle> TouchState::getWallpaperWindow() const { return nullptr; return nullptr; } } sp<WindowInfoHandle> TouchState::getWindow(const sp<IBinder>& token) const { for (const TouchedWindow& touchedWindow : windows) { const auto& windowHandle = touchedWindow.windowHandle; if (windowHandle->getToken() == token) { return windowHandle; } } return nullptr; } } // namespace android::inputdispatcher } // namespace android::inputdispatcher