Loading libs/input/input_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,16 @@ flag { bug: "330752824" } flag { name: "allow_transfer_of_entire_gesture" namespace: "input" description: "When calling 'transferTouchGesture', the entire gesture (including new POINTER_DOWN events from the same device) will be automatically transferred to the destination window" bug: "397979572" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_keyboard_classifier" namespace: "input" Loading services/inputflinger/dispatcher/InputDispatcher.cpp +39 −10 Original line number Diff line number Diff line Loading @@ -2510,6 +2510,24 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( return injectionError(InputEventInjectionResult::TARGET_MISMATCH); } if (newTouchedWindowHandle != nullptr && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) { // Check if this should be redirected to another window, in case this window previously // called 'transferTouch' for this gesture. const auto it = std::find_if(tempTouchState.windows.begin(), tempTouchState.windows.end(), [&](const TouchedWindow& touchedWindow) { return touchedWindow.forwardingWindowToken == newTouchedWindowHandle->getToken() && touchedWindow.hasTouchingPointers(entry.deviceId); }); if (it != tempTouchState.windows.end()) { LOG(INFO) << "Forwarding pointer from " << newTouchedWindowHandle->getName() << " to " << it->windowHandle->getName(); newTouchedWindowHandle = it->windowHandle; } } std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, mWindowInfos); if (newTouchedWindowHandle != nullptr) { Loading Loading @@ -2550,7 +2568,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( isDownOrPointerDown ? std::make_optional( entry.eventTime) : std::nullopt); : std::nullopt, /*forwardingWindowToken=*/nullptr); if (!addResult.ok()) { LOG(ERROR) << "Error while processing " << entry << " for " << windowHandle->getName(); Loading @@ -2577,7 +2596,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( tempTouchState.addOrUpdateWindow(wallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags, entry.deviceId, {pointer}, entry.eventTime); entry.eventTime, /*forwardingWindowToken=*/nullptr); } } } Loading Loading @@ -2676,7 +2696,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, InputTarget::DispatchMode::SLIPPERY_ENTER, targetFlags, entry.deviceId, {pointer}, entry.eventTime); entry.eventTime, /*forwardingWindowToken=*/nullptr); // Check if the wallpaper window should deliver the corresponding event. slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle, Loading Loading @@ -5833,7 +5854,7 @@ void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { } bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop) { bool isDragDrop, bool transferEntireGesture) { if (fromToken == toToken) { LOG_IF(INFO, DEBUG_FOCUS) << "Trivial transfer to same window."; return true; Loading @@ -5847,7 +5868,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s "transferring touch from this window to another window", traceContext.getTracker()); auto result = mTouchStates.transferTouchGesture(fromToken, toToken); auto result = mTouchStates.transferTouchGesture(fromToken, toToken, transferEntireGesture); if (!result.has_value()) { return false; } Loading Loading @@ -5891,7 +5912,8 @@ std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<Pointe std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>, std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>> InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken, const sp<android::IBinder>& toToken) { const sp<android::IBinder>& toToken, bool transferEntireGesture) { // Find the target touch state and touched window by fromToken. auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken); if (!touchStateWindowAndDisplay.has_value()) { Loading Loading @@ -5934,8 +5956,12 @@ InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IB } // Transferring touch focus using this API should not effect the focused window. newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE; sp<IBinder> forwardingWindowToken; if (transferEntireGesture && com::android::input::flags::allow_transfer_of_entire_gesture()) { forwardingWindowToken = fromToken; } state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags, deviceId, pointers, downTimeInTarget); deviceId, pointers, downTimeInTarget, forwardingWindowToken); // Synthesize cancel for old window and down for new window. std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken); Loading Loading @@ -6017,7 +6043,8 @@ bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken fromToken = from->getToken(); } // release lock return transferTouchGesture(fromToken, destChannelToken); return transferTouchGesture(fromToken, destChannelToken, /*isDragDrop=*/false, /*transferEntireGesture=*/false); } void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { Loading Loading @@ -7195,7 +7222,8 @@ void InputDispatcher::DispatcherTouchState::slipWallpaperTouch( state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER, InputTarget::Flags::WINDOW_IS_OBSCURED | InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED, deviceId, pointers, entry.eventTime); deviceId, pointers, entry.eventTime, /*forwardingWindowToken=*/nullptr); } } Loading Loading @@ -7236,7 +7264,8 @@ InputDispatcher::DispatcherTouchState::transferWallpaperTouch( wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED | InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags, deviceId, pointers, downTimeInTarget); deviceId, pointers, downTimeInTarget, /*forwardingWindowToken=*/nullptr); std::shared_ptr<Connection> wallpaperConnection = mConnectionManager.getConnection(newWallpaper->getToken()); if (wallpaperConnection != nullptr) { Loading services/inputflinger/dispatcher/InputDispatcher.h +3 −2 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ public: void setMaximumObscuringOpacityForTouch(float opacity) override; bool transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop = false) override; bool isDragDrop, bool transferEntireGesture) override; bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken, ui::LogicalDisplayId displayId) override; Loading Loading @@ -440,7 +440,8 @@ private: std::optional< std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>, std::list<CancellationArgs>, std::list<PointerDownArgs>>> transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken); transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool transferEntireGesture); base::Result<std::list<CancellationArgs>, status_t> pilferPointers( const sp<IBinder>& token, const Connection& requestingConnection); Loading services/inputflinger/dispatcher/TouchState.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( const sp<WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers, std::optional<nsecs_t> firstDownTimeInTarget) { std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken) { if (touchingPointers.empty()) { LOG(FATAL) << __func__ << "No pointers specified for " << windowHandle->getName(); return android::base::Error(); Loading @@ -88,6 +88,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( if (touchedWindow.windowHandle == windowHandle) { touchedWindow.dispatchMode = dispatchMode; touchedWindow.targetFlags |= targetFlags; touchedWindow.forwardingWindowToken = forwardingWindowToken; // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have // downTime set initially. Need to update existing window when a pointer is down for the // window. Loading @@ -103,6 +104,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( touchedWindow.windowHandle = windowHandle; touchedWindow.dispatchMode = dispatchMode; touchedWindow.targetFlags = targetFlags; touchedWindow.forwardingWindowToken = forwardingWindowToken; touchedWindow.addTouchingPointers(deviceId, touchingPointers); if (firstDownTimeInTarget) { touchedWindow.trySetDownTimeInTarget(deviceId, *firstDownTimeInTarget); Loading services/inputflinger/dispatcher/TouchState.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct TouchState { const sp<android::gui::WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers, std::optional<nsecs_t> firstDownTimeInTarget); std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken); void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, const PointerProperties& pointer, float x, float y); Loading Loading
libs/input/input_flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,16 @@ flag { bug: "330752824" } flag { name: "allow_transfer_of_entire_gesture" namespace: "input" description: "When calling 'transferTouchGesture', the entire gesture (including new POINTER_DOWN events from the same device) will be automatically transferred to the destination window" bug: "397979572" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "enable_keyboard_classifier" namespace: "input" Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +39 −10 Original line number Diff line number Diff line Loading @@ -2510,6 +2510,24 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( return injectionError(InputEventInjectionResult::TARGET_MISMATCH); } if (newTouchedWindowHandle != nullptr && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) { // Check if this should be redirected to another window, in case this window previously // called 'transferTouch' for this gesture. const auto it = std::find_if(tempTouchState.windows.begin(), tempTouchState.windows.end(), [&](const TouchedWindow& touchedWindow) { return touchedWindow.forwardingWindowToken == newTouchedWindowHandle->getToken() && touchedWindow.hasTouchingPointers(entry.deviceId); }); if (it != tempTouchState.windows.end()) { LOG(INFO) << "Forwarding pointer from " << newTouchedWindowHandle->getName() << " to " << it->windowHandle->getName(); newTouchedWindowHandle = it->windowHandle; } } std::vector<sp<WindowInfoHandle>> newTouchedWindows = findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, mWindowInfos); if (newTouchedWindowHandle != nullptr) { Loading Loading @@ -2550,7 +2568,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( isDownOrPointerDown ? std::make_optional( entry.eventTime) : std::nullopt); : std::nullopt, /*forwardingWindowToken=*/nullptr); if (!addResult.ok()) { LOG(ERROR) << "Error while processing " << entry << " for " << windowHandle->getName(); Loading @@ -2577,7 +2596,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( tempTouchState.addOrUpdateWindow(wallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags, entry.deviceId, {pointer}, entry.eventTime); entry.eventTime, /*forwardingWindowToken=*/nullptr); } } } Loading Loading @@ -2676,7 +2696,8 @@ InputDispatcher::DispatcherTouchState::findTouchedWindowTargets( tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, InputTarget::DispatchMode::SLIPPERY_ENTER, targetFlags, entry.deviceId, {pointer}, entry.eventTime); entry.eventTime, /*forwardingWindowToken=*/nullptr); // Check if the wallpaper window should deliver the corresponding event. slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle, Loading Loading @@ -5833,7 +5854,7 @@ void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) { } bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop) { bool isDragDrop, bool transferEntireGesture) { if (fromToken == toToken) { LOG_IF(INFO, DEBUG_FOCUS) << "Trivial transfer to same window."; return true; Loading @@ -5847,7 +5868,7 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s "transferring touch from this window to another window", traceContext.getTracker()); auto result = mTouchStates.transferTouchGesture(fromToken, toToken); auto result = mTouchStates.transferTouchGesture(fromToken, toToken, transferEntireGesture); if (!result.has_value()) { return false; } Loading Loading @@ -5891,7 +5912,8 @@ std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<Pointe std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>, std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>> InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken, const sp<android::IBinder>& toToken) { const sp<android::IBinder>& toToken, bool transferEntireGesture) { // Find the target touch state and touched window by fromToken. auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken); if (!touchStateWindowAndDisplay.has_value()) { Loading Loading @@ -5934,8 +5956,12 @@ InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IB } // Transferring touch focus using this API should not effect the focused window. newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE; sp<IBinder> forwardingWindowToken; if (transferEntireGesture && com::android::input::flags::allow_transfer_of_entire_gesture()) { forwardingWindowToken = fromToken; } state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags, deviceId, pointers, downTimeInTarget); deviceId, pointers, downTimeInTarget, forwardingWindowToken); // Synthesize cancel for old window and down for new window. std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken); Loading Loading @@ -6017,7 +6043,8 @@ bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken fromToken = from->getToken(); } // release lock return transferTouchGesture(fromToken, destChannelToken); return transferTouchGesture(fromToken, destChannelToken, /*isDragDrop=*/false, /*transferEntireGesture=*/false); } void InputDispatcher::resetAndDropEverythingLocked(const char* reason) { Loading Loading @@ -7195,7 +7222,8 @@ void InputDispatcher::DispatcherTouchState::slipWallpaperTouch( state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER, InputTarget::Flags::WINDOW_IS_OBSCURED | InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED, deviceId, pointers, entry.eventTime); deviceId, pointers, entry.eventTime, /*forwardingWindowToken=*/nullptr); } } Loading Loading @@ -7236,7 +7264,8 @@ InputDispatcher::DispatcherTouchState::transferWallpaperTouch( wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED | InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags, deviceId, pointers, downTimeInTarget); deviceId, pointers, downTimeInTarget, /*forwardingWindowToken=*/nullptr); std::shared_ptr<Connection> wallpaperConnection = mConnectionManager.getConnection(newWallpaper->getToken()); if (wallpaperConnection != nullptr) { Loading
services/inputflinger/dispatcher/InputDispatcher.h +3 −2 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ public: void setMaximumObscuringOpacityForTouch(float opacity) override; bool transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop = false) override; bool isDragDrop, bool transferEntireGesture) override; bool transferTouchOnDisplay(const sp<IBinder>& destChannelToken, ui::LogicalDisplayId displayId) override; Loading Loading @@ -440,7 +440,8 @@ private: std::optional< std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>, std::list<CancellationArgs>, std::list<PointerDownArgs>>> transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken); transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool transferEntireGesture); base::Result<std::list<CancellationArgs>, status_t> pilferPointers( const sp<IBinder>& token, const Connection& requestingConnection); Loading
services/inputflinger/dispatcher/TouchState.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( const sp<WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers, std::optional<nsecs_t> firstDownTimeInTarget) { std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken) { if (touchingPointers.empty()) { LOG(FATAL) << __func__ << "No pointers specified for " << windowHandle->getName(); return android::base::Error(); Loading @@ -88,6 +88,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( if (touchedWindow.windowHandle == windowHandle) { touchedWindow.dispatchMode = dispatchMode; touchedWindow.targetFlags |= targetFlags; touchedWindow.forwardingWindowToken = forwardingWindowToken; // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have // downTime set initially. Need to update existing window when a pointer is down for the // window. Loading @@ -103,6 +104,7 @@ android::base::Result<void> TouchState::addOrUpdateWindow( touchedWindow.windowHandle = windowHandle; touchedWindow.dispatchMode = dispatchMode; touchedWindow.targetFlags = targetFlags; touchedWindow.forwardingWindowToken = forwardingWindowToken; touchedWindow.addTouchingPointers(deviceId, touchingPointers); if (firstDownTimeInTarget) { touchedWindow.trySetDownTimeInTarget(deviceId, *firstDownTimeInTarget); Loading
services/inputflinger/dispatcher/TouchState.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct TouchState { const sp<android::gui::WindowInfoHandle>& windowHandle, InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId, const std::vector<PointerProperties>& touchingPointers, std::optional<nsecs_t> firstDownTimeInTarget); std::optional<nsecs_t> firstDownTimeInTarget, sp<IBinder> forwardingWindowToken); void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, DeviceId deviceId, const PointerProperties& pointer, float x, float y); Loading