Loading services/inputflinger/dispatcher/Entry.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,23 @@ std::string PointerCaptureChangedEntry::getDescription() const { pointerCaptureEnabled ? "true" : "false"); } // --- DragEntry --- // Drag notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries DragEntry::DragEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool isExiting, float x, float y) : EventEntry(id, Type::DRAG, eventTime, POLICY_FLAG_PASS_TO_USER), connectionToken(connectionToken), isExiting(isExiting), x(x), y(y) {} DragEntry::~DragEntry() {} std::string DragEntry::getDescription() const { return StringPrintf("DragEntry(isExiting=%s, x=%f, y=%f)", isExiting ? "true" : "false", x, y); } // --- KeyEntry --- KeyEntry::KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, Loading services/inputflinger/dispatcher/Entry.h +13 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct EventEntry { MOTION, SENSOR, POINTER_CAPTURE_CHANGED, DRAG, }; int32_t id; Loading Loading @@ -111,6 +112,18 @@ struct PointerCaptureChangedEntry : EventEntry { virtual ~PointerCaptureChangedEntry(); }; struct DragEntry : EventEntry { sp<IBinder> connectionToken; bool isExiting; float x, y; DragEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool isExiting, float x, float y); std::string getDescription() const override; ~DragEntry() override; }; struct KeyEntry : EventEntry { int32_t deviceId; uint32_t source; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +117 −10 Original line number Diff line number Diff line Loading @@ -753,6 +753,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { break; } case EventEntry::Type::DRAG: { std::shared_ptr<DragEntry> typedEntry = std::static_pointer_cast<DragEntry>(mPendingEvent); dispatchDragLocked(currentTime, typedEntry); done = true; break; } case EventEntry::Type::KEY: { std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent); if (isAppSwitchDue) { Loading Loading @@ -921,7 +929,8 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { // nothing to do break; } Loading @@ -943,7 +952,8 @@ void InputDispatcher::addRecentEventLocked(std::shared_ptr<EventEntry> entry) { sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool addOutsideTargets, bool addPortalWindows) { bool addPortalWindows, bool ignoreDragWindow) { if ((addPortalWindows || addOutsideTargets) && touchState == nullptr) { LOG_ALWAYS_FATAL( "Must provide a valid touch state if adding portal windows or outside targets"); Loading @@ -951,6 +961,9 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display // Traverse windows from front to back to find touched window. const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<InputWindowHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, touchState->dragWindow)) { continue; } const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo->displayId == displayId) { auto flags = windowInfo->flags; Loading Loading @@ -1060,7 +1073,8 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason case EventEntry::Type::SENSOR: { break; } case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { break; } case EventEntry::Type::FOCUS: Loading Loading @@ -1554,6 +1568,35 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr< return true; } void InputDispatcher::enqueueDragEventLocked(const sp<InputWindowHandle>& windowHandle, bool isExiting, const MotionEntry& motionEntry) { // If the window needs enqueue a drag event, the pointerCount should be 1 and the action should // be AMOTION_EVENT_ACTION_MOVE, that could guarantee the first pointer is always valid. LOG_ALWAYS_FATAL_IF(motionEntry.pointerCount != 1); PointerCoords pointerCoords; pointerCoords.copyFrom(motionEntry.pointerCoords[0]); pointerCoords.transform(windowHandle->getInfo()->transform); std::unique_ptr<DragEntry> dragEntry = std::make_unique<DragEntry>(mIdGenerator.nextId(), motionEntry.eventTime, windowHandle->getToken(), isExiting, pointerCoords.getX(), pointerCoords.getY()); enqueueInboundEventLocked(std::move(dragEntry)); } void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) { std::shared_ptr<InputChannel> channel = getInputChannelLocked(entry->connectionToken); if (channel == nullptr) { return; // Window has gone away } InputTarget target; target.inputChannel = channel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); } void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) { #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 Loading Loading @@ -1660,7 +1703,8 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { ALOGE("%s events do not have a target display", NamedEnum::string(entry.type).c_str()); return ADISPLAY_ID_NONE; } Loading Loading @@ -2017,6 +2061,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( goto Failed; } addDragEventLocked(entry, tempTouchState); // Check whether touches should slip outside of the current foreground window. if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 && tempTouchState.isSlippery()) { Loading Loading @@ -2272,6 +2318,38 @@ Failed: return injectionResult; } void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& state) { if (entry.pointerCount != 1 || !state.dragWindow) { return; } int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK; int32_t x = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); if (maskedAction == AMOTION_EVENT_ACTION_MOVE) { const sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(entry.displayId, x, y, &state, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); // enqueue drag exit if needed. if (hoverWindowHandle != state.dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, state.dragHoverWindowHandle)) { if (state.dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(state.dragHoverWindowHandle, true /*isExiting*/, entry); } state.dragHoverWindowHandle = hoverWindowHandle; } // enqueue drag location if needed. if (hoverWindowHandle != nullptr) { enqueueDragEventLocked(hoverWindowHandle, false /*isExiting*/, entry); } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } } void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) { Loading Loading @@ -2543,7 +2621,8 @@ std::string InputDispatcher::getApplicationWindowLabel( void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (eventEntry.type == EventEntry::Type::FOCUS || eventEntry.type == EventEntry::Type::POINTER_CAPTURE_CHANGED) { eventEntry.type == EventEntry::Type::POINTER_CAPTURE_CHANGED || eventEntry.type == EventEntry::Type::DRAG) { // Focus or pointer capture changed events are passed to apps, but do not represent user // activity. return; Loading Loading @@ -2585,7 +2664,8 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s events are not user activity", NamedEnum::string(eventEntry.type).c_str()); break; Loading Loading @@ -2799,7 +2879,8 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio break; } case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { break; } case EventEntry::Type::SENSOR: { Loading Loading @@ -3022,6 +3103,15 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, break; } case EventEntry::Type::DRAG: { const DragEntry& dragEntry = static_cast<const DragEntry&>(eventEntry); status = connection->inputPublisher.publishDragEvent(dispatchEntry->seq, dragEntry.id, dragEntry.x, dragEntry.y, dragEntry.isExiting); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { Loading Loading @@ -3319,7 +3409,8 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( break; } case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("Canceling %s events is not supported", NamedEnum::string(cancelationEventEntry->type).c_str()); break; Loading Loading @@ -3384,7 +3475,8 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::SENSOR: { case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", NamedEnum::string(downEventEntry->type).c_str()); break; Loading Loading @@ -4348,6 +4440,15 @@ void InputDispatcher::setInputWindowsLocked( ++i; } } // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. we // could just clear the state here. if (state.dragWindow && std::find(windowHandles.begin(), windowHandles.end(), state.dragWindow) == windowHandles.end()) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } } // Release information for windows that are no longer present. Loading Loading @@ -4538,7 +4639,8 @@ void InputDispatcher::setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mod mBlockUntrustedTouchesMode = mode; } bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop) { if (fromToken == toToken) { if (DEBUG_FOCUS) { ALOGD("Trivial transfer to same window."); Loading Loading @@ -4582,6 +4684,11 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< InputTarget::FLAG_DISPATCH_AS_IS); state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); // Store the dragging window. if (isDragDrop) { state.dragWindow = toWindowHandle; } found = true; goto Found; } Loading services/inputflinger/dispatcher/InputDispatcher.h +11 −4 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ public: virtual void setMaximumObscuringOpacityForTouch(float opacity) override; virtual void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override; virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) override; virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop = false) override; virtual base::Result<std::unique_ptr<InputChannel>> createInputChannel( const std::string& name) override; Loading Loading @@ -185,6 +185,9 @@ private: // Enqueues a focus event. void enqueueFocusEventLocked(const sp<IBinder>& windowToken, bool hasFocus, const std::string& reason) REQUIRES(mLock); // Enqueues a drag event. void enqueueDragEventLocked(const sp<InputWindowHandle>& windowToken, bool isExiting, const MotionEntry& motionEntry) REQUIRES(mLock); // Adds an event to a queue of recent events for debugging purposes. void addRecentEventLocked(std::shared_ptr<EventEntry> entry) REQUIRES(mLock); Loading @@ -204,7 +207,8 @@ private: sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool addOutsideTargets = false, bool addPortalWindows = false) REQUIRES(mLock); bool addPortalWindows = false, bool ignoreDragWindow = false) REQUIRES(mLock); // All registered connections mapped by channel file descriptor. std::unordered_map<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock); Loading Loading @@ -387,6 +391,7 @@ private: const std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr<SensorEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) REQUIRES(mLock); void logOutboundKeyDetails(const char* prefix, const KeyEntry& entry); void logOutboundMotionDetails(const char* prefix, const MotionEntry& entry); Loading Loading @@ -489,10 +494,12 @@ private: std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, const InjectionState* injectionState); // Enqueue a drag event if needed, and update the touch state. // Uses findTouchedWindowTargetsLocked to make the decision void addDragEventLocked(const MotionEntry& entry, TouchState& state) REQUIRES(mLock); struct TouchOcclusionInfo { bool hasBlockingOcclusion; Loading services/inputflinger/dispatcher/TouchState.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ void TouchState::copyFrom(const TouchState& other) { windows = other.windows; portalWindows = other.portalWindows; gestureMonitors = other.gestureMonitors; dragHoverWindowHandle = other.dragHoverWindowHandle; dragWindow = other.dragWindow; } void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, Loading Loading
services/inputflinger/dispatcher/Entry.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,23 @@ std::string PointerCaptureChangedEntry::getDescription() const { pointerCaptureEnabled ? "true" : "false"); } // --- DragEntry --- // Drag notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries DragEntry::DragEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool isExiting, float x, float y) : EventEntry(id, Type::DRAG, eventTime, POLICY_FLAG_PASS_TO_USER), connectionToken(connectionToken), isExiting(isExiting), x(x), y(y) {} DragEntry::~DragEntry() {} std::string DragEntry::getDescription() const { return StringPrintf("DragEntry(isExiting=%s, x=%f, y=%f)", isExiting ? "true" : "false", x, y); } // --- KeyEntry --- KeyEntry::KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, Loading
services/inputflinger/dispatcher/Entry.h +13 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct EventEntry { MOTION, SENSOR, POINTER_CAPTURE_CHANGED, DRAG, }; int32_t id; Loading Loading @@ -111,6 +112,18 @@ struct PointerCaptureChangedEntry : EventEntry { virtual ~PointerCaptureChangedEntry(); }; struct DragEntry : EventEntry { sp<IBinder> connectionToken; bool isExiting; float x, y; DragEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool isExiting, float x, float y); std::string getDescription() const override; ~DragEntry() override; }; struct KeyEntry : EventEntry { int32_t deviceId; uint32_t source; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +117 −10 Original line number Diff line number Diff line Loading @@ -753,6 +753,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { break; } case EventEntry::Type::DRAG: { std::shared_ptr<DragEntry> typedEntry = std::static_pointer_cast<DragEntry>(mPendingEvent); dispatchDragLocked(currentTime, typedEntry); done = true; break; } case EventEntry::Type::KEY: { std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent); if (isAppSwitchDue) { Loading Loading @@ -921,7 +929,8 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { // nothing to do break; } Loading @@ -943,7 +952,8 @@ void InputDispatcher::addRecentEventLocked(std::shared_ptr<EventEntry> entry) { sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool addOutsideTargets, bool addPortalWindows) { bool addPortalWindows, bool ignoreDragWindow) { if ((addPortalWindows || addOutsideTargets) && touchState == nullptr) { LOG_ALWAYS_FATAL( "Must provide a valid touch state if adding portal windows or outside targets"); Loading @@ -951,6 +961,9 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display // Traverse windows from front to back to find touched window. const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<InputWindowHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, touchState->dragWindow)) { continue; } const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo->displayId == displayId) { auto flags = windowInfo->flags; Loading Loading @@ -1060,7 +1073,8 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason case EventEntry::Type::SENSOR: { break; } case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { break; } case EventEntry::Type::FOCUS: Loading Loading @@ -1554,6 +1568,35 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr< return true; } void InputDispatcher::enqueueDragEventLocked(const sp<InputWindowHandle>& windowHandle, bool isExiting, const MotionEntry& motionEntry) { // If the window needs enqueue a drag event, the pointerCount should be 1 and the action should // be AMOTION_EVENT_ACTION_MOVE, that could guarantee the first pointer is always valid. LOG_ALWAYS_FATAL_IF(motionEntry.pointerCount != 1); PointerCoords pointerCoords; pointerCoords.copyFrom(motionEntry.pointerCoords[0]); pointerCoords.transform(windowHandle->getInfo()->transform); std::unique_ptr<DragEntry> dragEntry = std::make_unique<DragEntry>(mIdGenerator.nextId(), motionEntry.eventTime, windowHandle->getToken(), isExiting, pointerCoords.getX(), pointerCoords.getY()); enqueueInboundEventLocked(std::move(dragEntry)); } void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) { std::shared_ptr<InputChannel> channel = getInputChannelLocked(entry->connectionToken); if (channel == nullptr) { return; // Window has gone away } InputTarget target; target.inputChannel = channel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); } void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) { #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 Loading Loading @@ -1660,7 +1703,8 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { ALOGE("%s events do not have a target display", NamedEnum::string(entry.type).c_str()); return ADISPLAY_ID_NONE; } Loading Loading @@ -2017,6 +2061,8 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( goto Failed; } addDragEventLocked(entry, tempTouchState); // Check whether touches should slip outside of the current foreground window. if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 && tempTouchState.isSlippery()) { Loading Loading @@ -2272,6 +2318,38 @@ Failed: return injectionResult; } void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& state) { if (entry.pointerCount != 1 || !state.dragWindow) { return; } int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK; int32_t x = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); if (maskedAction == AMOTION_EVENT_ACTION_MOVE) { const sp<InputWindowHandle> hoverWindowHandle = findTouchedWindowAtLocked(entry.displayId, x, y, &state, false /*addOutsideTargets*/, false /*addPortalWindows*/, true /*ignoreDragWindow*/); // enqueue drag exit if needed. if (hoverWindowHandle != state.dragHoverWindowHandle && !haveSameToken(hoverWindowHandle, state.dragHoverWindowHandle)) { if (state.dragHoverWindowHandle != nullptr) { enqueueDragEventLocked(state.dragHoverWindowHandle, true /*isExiting*/, entry); } state.dragHoverWindowHandle = hoverWindowHandle; } // enqueue drag location if needed. if (hoverWindowHandle != nullptr) { enqueueDragEventLocked(hoverWindowHandle, false /*isExiting*/, entry); } } else if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } } void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) { Loading Loading @@ -2543,7 +2621,8 @@ std::string InputDispatcher::getApplicationWindowLabel( void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { if (eventEntry.type == EventEntry::Type::FOCUS || eventEntry.type == EventEntry::Type::POINTER_CAPTURE_CHANGED) { eventEntry.type == EventEntry::Type::POINTER_CAPTURE_CHANGED || eventEntry.type == EventEntry::Type::DRAG) { // Focus or pointer capture changed events are passed to apps, but do not represent user // activity. return; Loading Loading @@ -2585,7 +2664,8 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s events are not user activity", NamedEnum::string(eventEntry.type).c_str()); break; Loading Loading @@ -2799,7 +2879,8 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio break; } case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { break; } case EventEntry::Type::SENSOR: { Loading Loading @@ -3022,6 +3103,15 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, break; } case EventEntry::Type::DRAG: { const DragEntry& dragEntry = static_cast<const DragEntry&>(eventEntry); status = connection->inputPublisher.publishDragEvent(dispatchEntry->seq, dragEntry.id, dragEntry.x, dragEntry.y, dragEntry.isExiting); break; } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::SENSOR: { Loading Loading @@ -3319,7 +3409,8 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( break; } case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("Canceling %s events is not supported", NamedEnum::string(cancelationEventEntry->type).c_str()); break; Loading Loading @@ -3384,7 +3475,8 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::SENSOR: { case EventEntry::Type::SENSOR: case EventEntry::Type::DRAG: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", NamedEnum::string(downEventEntry->type).c_str()); break; Loading Loading @@ -4348,6 +4440,15 @@ void InputDispatcher::setInputWindowsLocked( ++i; } } // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. we // could just clear the state here. if (state.dragWindow && std::find(windowHandles.begin(), windowHandles.end(), state.dragWindow) == windowHandles.end()) { state.dragWindow = nullptr; state.dragHoverWindowHandle = nullptr; } } // Release information for windows that are no longer present. Loading Loading @@ -4538,7 +4639,8 @@ void InputDispatcher::setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mod mBlockUntrustedTouchesMode = mode; } bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop) { if (fromToken == toToken) { if (DEBUG_FOCUS) { ALOGD("Trivial transfer to same window."); Loading Loading @@ -4582,6 +4684,11 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< InputTarget::FLAG_DISPATCH_AS_IS); state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds); // Store the dragging window. if (isDragDrop) { state.dragWindow = toWindowHandle; } found = true; goto Found; } Loading
services/inputflinger/dispatcher/InputDispatcher.h +11 −4 Original line number Diff line number Diff line Loading @@ -120,8 +120,8 @@ public: virtual void setMaximumObscuringOpacityForTouch(float opacity) override; virtual void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override; virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) override; virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken, bool isDragDrop = false) override; virtual base::Result<std::unique_ptr<InputChannel>> createInputChannel( const std::string& name) override; Loading Loading @@ -185,6 +185,9 @@ private: // Enqueues a focus event. void enqueueFocusEventLocked(const sp<IBinder>& windowToken, bool hasFocus, const std::string& reason) REQUIRES(mLock); // Enqueues a drag event. void enqueueDragEventLocked(const sp<InputWindowHandle>& windowToken, bool isExiting, const MotionEntry& motionEntry) REQUIRES(mLock); // Adds an event to a queue of recent events for debugging purposes. void addRecentEventLocked(std::shared_ptr<EventEntry> entry) REQUIRES(mLock); Loading @@ -204,7 +207,8 @@ private: sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, TouchState* touchState, bool addOutsideTargets = false, bool addPortalWindows = false) REQUIRES(mLock); bool addPortalWindows = false, bool ignoreDragWindow = false) REQUIRES(mLock); // All registered connections mapped by channel file descriptor. std::unordered_map<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock); Loading Loading @@ -387,6 +391,7 @@ private: const std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr<SensorEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) REQUIRES(mLock); void logOutboundKeyDetails(const char* prefix, const KeyEntry& entry); void logOutboundMotionDetails(const char* prefix, const MotionEntry& entry); Loading Loading @@ -489,10 +494,12 @@ private: std::vector<InputTarget>& inputTargets) REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock); bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle, const InjectionState* injectionState); // Enqueue a drag event if needed, and update the touch state. // Uses findTouchedWindowTargetsLocked to make the decision void addDragEventLocked(const MotionEntry& entry, TouchState& state) REQUIRES(mLock); struct TouchOcclusionInfo { bool hasBlockingOcclusion; Loading
services/inputflinger/dispatcher/TouchState.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ void TouchState::copyFrom(const TouchState& other) { windows = other.windows; portalWindows = other.portalWindows; gestureMonitors = other.gestureMonitors; dragHoverWindowHandle = other.dragHoverWindowHandle; dragWindow = other.dragWindow; } void TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, Loading