Loading services/inputflinger/dispatcher/InputDispatcher.cpp +41 −103 Original line number Diff line number Diff line Loading @@ -256,67 +256,6 @@ static bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; } static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, EventEntry* eventEntry, int32_t inputTargetFlags) { if (inputTarget.useDefaultPointerInfo()) { const PointerInfo& pointerInfo = inputTarget.getDefaultPointerInfo(); return std::make_unique<DispatchEntry>(eventEntry, // increments ref inputTargetFlags, pointerInfo.xOffset, pointerInfo.yOffset, inputTarget.globalScaleFactor, pointerInfo.windowXScale, pointerInfo.windowYScale); } ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION); const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); PointerCoords pointerCoords[MAX_POINTERS]; // Use the first pointer information to normalize all other pointers. This could be any pointer // as long as all other pointers are normalized to the same value and the final DispatchEntry // uses the offset and scale for the normalized pointer. const PointerInfo& firstPointerInfo = inputTarget.pointerInfos[inputTarget.pointerIds.firstMarkedBit()]; // Iterate through all pointers in the event to normalize against the first. for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount; pointerIndex++) { const PointerProperties& pointerProperties = motionEntry.pointerProperties[pointerIndex]; uint32_t pointerId = uint32_t(pointerProperties.id); const PointerInfo& currPointerInfo = inputTarget.pointerInfos[pointerId]; // The scale factor is the ratio of the current pointers scale to the normalized scale. float scaleXDiff = currPointerInfo.windowXScale / firstPointerInfo.windowXScale; float scaleYDiff = currPointerInfo.windowYScale / firstPointerInfo.windowYScale; pointerCoords[pointerIndex].copyFrom(motionEntry.pointerCoords[pointerIndex]); // First apply the current pointers offset to set the window at 0,0 pointerCoords[pointerIndex].applyOffset(currPointerInfo.xOffset, currPointerInfo.yOffset); // Next scale the coordinates. pointerCoords[pointerIndex].scale(1, scaleXDiff, scaleYDiff); // Lastly, offset the coordinates so they're in the normalized pointer's frame. pointerCoords[pointerIndex].applyOffset(-firstPointerInfo.xOffset, -firstPointerInfo.yOffset); } MotionEntry* combinedMotionEntry = new MotionEntry(motionEntry.sequenceNum, motionEntry.eventTime, motionEntry.deviceId, motionEntry.source, motionEntry.displayId, motionEntry.policyFlags, motionEntry.action, motionEntry.actionButton, motionEntry.flags, motionEntry.metaState, motionEntry.buttonState, motionEntry.classification, motionEntry.edgeFlags, motionEntry.xPrecision, motionEntry.yPrecision, motionEntry.xCursorPosition, motionEntry.yCursorPosition, motionEntry.downTime, motionEntry.pointerCount, motionEntry.pointerProperties, pointerCoords, 0 /* xOffset */, 0 /* yOffset */); return std::make_unique<DispatchEntry>(combinedMotionEntry, // increments ref inputTargetFlags, firstPointerInfo.xOffset, firstPointerInfo.yOffset, inputTarget.globalScaleFactor, firstPointerInfo.windowXScale, firstPointerInfo.windowYScale); } // --- InputDispatcherThread --- class InputDispatcher::InputDispatcherThread : public Thread { Loading Loading @@ -1876,34 +1815,23 @@ Unresponsive: void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) { std::vector<InputTarget>::iterator it = std::find_if(inputTargets.begin(), inputTargets.end(), [&windowHandle](const InputTarget& inputTarget) { return inputTarget.inputChannel->getConnectionToken() == windowHandle->getToken(); }); const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (it == inputTargets.end()) { InputTarget inputTarget; sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken()); if (inputChannel == nullptr) { ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str()); return; } inputTarget.inputChannel = inputChannel; inputTarget.flags = targetFlags; inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; inputTargets.push_back(inputTarget); it = inputTargets.end() - 1; } ALOG_ASSERT(it->flags == targetFlags); ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor); it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop, windowInfo->windowXScale, windowInfo->windowYScale); const InputWindowInfo* windowInfo = windowHandle->getInfo(); InputTarget target; target.inputChannel = inputChannel; target.flags = targetFlags; target.xOffset = -windowInfo->frameLeft; target.yOffset = -windowInfo->frameTop; target.globalScaleFactor = windowInfo->globalScaleFactor; target.windowXScale = windowInfo->windowXScale; target.windowYScale = windowInfo->windowYScale; target.pointerIds = pointerIds; inputTargets.push_back(target); } void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, Loading @@ -1926,7 +1854,10 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */); target.xOffset = xOffset; target.yOffset = yOffset; target.pointerIds.clear(); target.globalScaleFactor = 1.0f; inputTargets.push_back(target); } Loading Loading @@ -2158,10 +2089,11 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, } #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " "globalScaleFactor=%f, pointerIds=0x%x %s", connection->getInputChannelName().c_str(), inputTarget.flags, inputTarget.globalScaleFactor, inputTarget.pointerIds.value, inputTarget.getPointerInfoString().c_str()); "xOffset=%f, yOffset=%f, globalScaleFactor=%f, " "windowScaleFactor=(%f, %f), pointerIds=0x%x", connection->getInputChannelName().c_str(), inputTarget.flags, inputTarget.xOffset, inputTarget.yOffset, inputTarget.globalScaleFactor, inputTarget.windowXScale, inputTarget.windowYScale, inputTarget.pointerIds.value); #endif // Skip this event if the connection status is not normal. Loading Loading @@ -2255,15 +2187,15 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio // This is a new event. // Enqueue a new dispatch entry onto the outbound queue for this connection. std::unique_ptr<DispatchEntry> dispatchEntry = createDispatchEntry(inputTarget, eventEntry, inputTargetFlags); std::make_unique<DispatchEntry>(eventEntry, // increments ref inputTargetFlags, inputTarget.xOffset, inputTarget.yOffset, inputTarget.globalScaleFactor, inputTarget.windowXScale, inputTarget.windowYScale); // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a // different EventEntry than what was passed in. EventEntry* newEntry = dispatchEntry->eventEntry; // Apply target flags and update the connection's input state. switch (newEntry->type) { switch (eventEntry->type) { case EventEntry::Type::KEY: { const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry); const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*eventEntry); dispatchEntry->resolvedAction = keyEntry.action; dispatchEntry->resolvedFlags = keyEntry.flags; Loading @@ -2279,7 +2211,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio } case EventEntry::Type::MOTION: { const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*newEntry); const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE; } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) { Loading Loading @@ -2333,14 +2265,14 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", EventEntry::typeToString(newEntry->type)); EventEntry::typeToString(eventEntry->type)); break; } } // Remember that we are waiting for this dispatch to complete. if (dispatchEntry->hasForegroundTarget()) { incrementPendingForegroundDispatches(newEntry); incrementPendingForegroundDispatches(eventEntry); } // Enqueue the dispatch entry. Loading Loading @@ -2729,9 +2661,15 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop, windowInfo->windowXScale, windowInfo->windowYScale); target.xOffset = -windowInfo->frameLeft; target.yOffset = -windowInfo->frameTop; target.globalScaleFactor = windowInfo->globalScaleFactor; target.windowXScale = windowInfo->windowXScale; target.windowYScale = windowInfo->windowYScale; } else { target.xOffset = 0; target.yOffset = 0; target.globalScaleFactor = 1.0f; } target.inputChannel = connection->inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; Loading services/inputflinger/dispatcher/InputTarget.cpp +0 −59 Original line number Diff line number Diff line Loading @@ -42,63 +42,4 @@ std::string dispatchModeToString(int32_t dispatchMode) { return StringPrintf("%" PRId32, dispatchMode); } void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffset, float windowXScale, float windowYScale) { // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors // and non splittable windows since we will just use all the pointers from the input event. if (newPointerIds.isEmpty()) { setDefaultPointerInfo(xOffset, yOffset, windowXScale, windowYScale); return; } // Ensure that the new set of pointers doesn't overlap with the current set of pointers. ALOG_ASSERT((pointerIds & newPointerIds) == 0); pointerIds |= newPointerIds; while (!newPointerIds.isEmpty()) { int32_t pointerId = newPointerIds.clearFirstMarkedBit(); pointerInfos[pointerId].xOffset = xOffset; pointerInfos[pointerId].yOffset = yOffset; pointerInfos[pointerId].windowXScale = windowXScale; pointerInfos[pointerId].windowYScale = windowYScale; } } void InputTarget::setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, float windowYScale) { pointerIds.clear(); pointerInfos[0].xOffset = xOffset; pointerInfos[0].yOffset = yOffset; pointerInfos[0].windowXScale = windowXScale; pointerInfos[0].windowYScale = windowYScale; } bool InputTarget::useDefaultPointerInfo() const { return pointerIds.isEmpty(); } const PointerInfo& InputTarget::getDefaultPointerInfo() const { return pointerInfos[0]; } std::string InputTarget::getPointerInfoString() const { if (useDefaultPointerInfo()) { const PointerInfo& pointerInfo = getDefaultPointerInfo(); return StringPrintf("xOffset=%.1f, yOffset=%.1f windowScaleFactor=(%.1f, %.1f)", pointerInfo.xOffset, pointerInfo.yOffset, pointerInfo.windowXScale, pointerInfo.windowYScale); } std::string out; for (uint32_t i = pointerIds.firstMarkedBit(); i <= pointerIds.lastMarkedBit(); i++) { if (!pointerIds.hasBit(i)) { continue; } out += StringPrintf("\n pointerId %d: xOffset=%.1f, yOffset=%.1f " "windowScaleFactor=(%.1f, %.1f)", i, pointerInfos[i].xOffset, pointerInfos[i].yOffset, pointerInfos[i].windowXScale, pointerInfos[i].windowYScale); } return out; } } // namespace android::inputdispatcher services/inputflinger/dispatcher/InputTarget.h +7 −40 Original line number Diff line number Diff line Loading @@ -23,22 +23,6 @@ namespace android::inputdispatcher { /* * Information about each pointer for an InputTarget. This includes offset and scale so * all pointers can be normalized to a single offset and scale. * * These values are ignored for KeyEvents */ struct PointerInfo { // The x and y offset to add to a MotionEvent as it is delivered. float xOffset = 0.0f; float yOffset = 0.0f; // Scaling factor to apply to MotionEvent as it is delivered. float windowXScale = 1.0f; float windowYScale = 1.0f; }; /* * An input target specifies how an input event is to be dispatched to a particular window * including the window's input channel, control flags, a timeout, and an X / Y offset to Loading Loading @@ -111,37 +95,20 @@ struct InputTarget { // Flags for the input target. int32_t flags = 0; // The x and y offset to add to a MotionEvent as it is delivered. // (ignored for KeyEvents) float xOffset = 0.0f; float yOffset = 0.0f; // Scaling factor to apply to MotionEvent as it is delivered. // (ignored for KeyEvents) float globalScaleFactor = 1.0f; float windowXScale = 1.0f; float windowYScale = 1.0f; // The subset of pointer ids to include in motion events dispatched to this input target // if FLAG_SPLIT is set. BitSet32 pointerIds; // The data is stored by the pointerId. Use the bit position of pointerIds to look up // PointerInfo per pointerId. PointerInfo pointerInfos[MAX_POINTERS]; void addPointers(BitSet32 pointerIds, float xOffset, float yOffset, float windowXScale, float windowYScale); void setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, float windowYScale); /** * Returns whether the default pointer information should be used. This will be true when the * InputTarget doesn't have any bits set in the pointerIds bitset. This can happen for monitors * and non splittable windows since we want all pointers for the EventEntry to go to this * target. */ bool useDefaultPointerInfo() const; /** * Returns the default PointerInfo object. This should be used when useDefaultPointerInfo is * true. */ const PointerInfo& getDefaultPointerInfo() const; std::string getPointerInfoString() const; }; std::string dispatchModeToString(int32_t dispatchMode); Loading services/inputflinger/tests/InputDispatcher_test.cpp +0 −103 Original line number Diff line number Diff line Loading @@ -1571,107 +1571,4 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) { mWindow1->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); } } // namespace android::inputdispatcher Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +41 −103 Original line number Diff line number Diff line Loading @@ -256,67 +256,6 @@ static bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) { return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT; } static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, EventEntry* eventEntry, int32_t inputTargetFlags) { if (inputTarget.useDefaultPointerInfo()) { const PointerInfo& pointerInfo = inputTarget.getDefaultPointerInfo(); return std::make_unique<DispatchEntry>(eventEntry, // increments ref inputTargetFlags, pointerInfo.xOffset, pointerInfo.yOffset, inputTarget.globalScaleFactor, pointerInfo.windowXScale, pointerInfo.windowYScale); } ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION); const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); PointerCoords pointerCoords[MAX_POINTERS]; // Use the first pointer information to normalize all other pointers. This could be any pointer // as long as all other pointers are normalized to the same value and the final DispatchEntry // uses the offset and scale for the normalized pointer. const PointerInfo& firstPointerInfo = inputTarget.pointerInfos[inputTarget.pointerIds.firstMarkedBit()]; // Iterate through all pointers in the event to normalize against the first. for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.pointerCount; pointerIndex++) { const PointerProperties& pointerProperties = motionEntry.pointerProperties[pointerIndex]; uint32_t pointerId = uint32_t(pointerProperties.id); const PointerInfo& currPointerInfo = inputTarget.pointerInfos[pointerId]; // The scale factor is the ratio of the current pointers scale to the normalized scale. float scaleXDiff = currPointerInfo.windowXScale / firstPointerInfo.windowXScale; float scaleYDiff = currPointerInfo.windowYScale / firstPointerInfo.windowYScale; pointerCoords[pointerIndex].copyFrom(motionEntry.pointerCoords[pointerIndex]); // First apply the current pointers offset to set the window at 0,0 pointerCoords[pointerIndex].applyOffset(currPointerInfo.xOffset, currPointerInfo.yOffset); // Next scale the coordinates. pointerCoords[pointerIndex].scale(1, scaleXDiff, scaleYDiff); // Lastly, offset the coordinates so they're in the normalized pointer's frame. pointerCoords[pointerIndex].applyOffset(-firstPointerInfo.xOffset, -firstPointerInfo.yOffset); } MotionEntry* combinedMotionEntry = new MotionEntry(motionEntry.sequenceNum, motionEntry.eventTime, motionEntry.deviceId, motionEntry.source, motionEntry.displayId, motionEntry.policyFlags, motionEntry.action, motionEntry.actionButton, motionEntry.flags, motionEntry.metaState, motionEntry.buttonState, motionEntry.classification, motionEntry.edgeFlags, motionEntry.xPrecision, motionEntry.yPrecision, motionEntry.xCursorPosition, motionEntry.yCursorPosition, motionEntry.downTime, motionEntry.pointerCount, motionEntry.pointerProperties, pointerCoords, 0 /* xOffset */, 0 /* yOffset */); return std::make_unique<DispatchEntry>(combinedMotionEntry, // increments ref inputTargetFlags, firstPointerInfo.xOffset, firstPointerInfo.yOffset, inputTarget.globalScaleFactor, firstPointerInfo.windowXScale, firstPointerInfo.windowYScale); } // --- InputDispatcherThread --- class InputDispatcher::InputDispatcherThread : public Thread { Loading Loading @@ -1876,34 +1815,23 @@ Unresponsive: void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector<InputTarget>& inputTargets) { std::vector<InputTarget>::iterator it = std::find_if(inputTargets.begin(), inputTargets.end(), [&windowHandle](const InputTarget& inputTarget) { return inputTarget.inputChannel->getConnectionToken() == windowHandle->getToken(); }); const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (it == inputTargets.end()) { InputTarget inputTarget; sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken()); if (inputChannel == nullptr) { ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str()); return; } inputTarget.inputChannel = inputChannel; inputTarget.flags = targetFlags; inputTarget.globalScaleFactor = windowInfo->globalScaleFactor; inputTargets.push_back(inputTarget); it = inputTargets.end() - 1; } ALOG_ASSERT(it->flags == targetFlags); ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor); it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop, windowInfo->windowXScale, windowInfo->windowYScale); const InputWindowInfo* windowInfo = windowHandle->getInfo(); InputTarget target; target.inputChannel = inputChannel; target.flags = targetFlags; target.xOffset = -windowInfo->frameLeft; target.yOffset = -windowInfo->frameTop; target.globalScaleFactor = windowInfo->globalScaleFactor; target.windowXScale = windowInfo->windowXScale; target.windowYScale = windowInfo->windowYScale; target.pointerIds = pointerIds; inputTargets.push_back(target); } void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, Loading @@ -1926,7 +1854,10 @@ void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xO InputTarget target; target.inputChannel = monitor.inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; target.setDefaultPointerInfo(xOffset, yOffset, 1 /* windowXScale */, 1 /* windowYScale */); target.xOffset = xOffset; target.yOffset = yOffset; target.pointerIds.clear(); target.globalScaleFactor = 1.0f; inputTargets.push_back(target); } Loading Loading @@ -2158,10 +2089,11 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, } #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " "globalScaleFactor=%f, pointerIds=0x%x %s", connection->getInputChannelName().c_str(), inputTarget.flags, inputTarget.globalScaleFactor, inputTarget.pointerIds.value, inputTarget.getPointerInfoString().c_str()); "xOffset=%f, yOffset=%f, globalScaleFactor=%f, " "windowScaleFactor=(%f, %f), pointerIds=0x%x", connection->getInputChannelName().c_str(), inputTarget.flags, inputTarget.xOffset, inputTarget.yOffset, inputTarget.globalScaleFactor, inputTarget.windowXScale, inputTarget.windowYScale, inputTarget.pointerIds.value); #endif // Skip this event if the connection status is not normal. Loading Loading @@ -2255,15 +2187,15 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio // This is a new event. // Enqueue a new dispatch entry onto the outbound queue for this connection. std::unique_ptr<DispatchEntry> dispatchEntry = createDispatchEntry(inputTarget, eventEntry, inputTargetFlags); std::make_unique<DispatchEntry>(eventEntry, // increments ref inputTargetFlags, inputTarget.xOffset, inputTarget.yOffset, inputTarget.globalScaleFactor, inputTarget.windowXScale, inputTarget.windowYScale); // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a // different EventEntry than what was passed in. EventEntry* newEntry = dispatchEntry->eventEntry; // Apply target flags and update the connection's input state. switch (newEntry->type) { switch (eventEntry->type) { case EventEntry::Type::KEY: { const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry); const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*eventEntry); dispatchEntry->resolvedAction = keyEntry.action; dispatchEntry->resolvedFlags = keyEntry.flags; Loading @@ -2279,7 +2211,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio } case EventEntry::Type::MOTION: { const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*newEntry); const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry); if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE; } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) { Loading Loading @@ -2333,14 +2265,14 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", EventEntry::typeToString(newEntry->type)); EventEntry::typeToString(eventEntry->type)); break; } } // Remember that we are waiting for this dispatch to complete. if (dispatchEntry->hasForegroundTarget()) { incrementPendingForegroundDispatches(newEntry); incrementPendingForegroundDispatches(eventEntry); } // Enqueue the dispatch entry. Loading Loading @@ -2729,9 +2661,15 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( getWindowHandleLocked(connection->inputChannel->getConnectionToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); target.setDefaultPointerInfo(-windowInfo->frameLeft, -windowInfo->frameTop, windowInfo->windowXScale, windowInfo->windowYScale); target.xOffset = -windowInfo->frameLeft; target.yOffset = -windowInfo->frameTop; target.globalScaleFactor = windowInfo->globalScaleFactor; target.windowXScale = windowInfo->windowXScale; target.windowYScale = windowInfo->windowYScale; } else { target.xOffset = 0; target.yOffset = 0; target.globalScaleFactor = 1.0f; } target.inputChannel = connection->inputChannel; target.flags = InputTarget::FLAG_DISPATCH_AS_IS; Loading
services/inputflinger/dispatcher/InputTarget.cpp +0 −59 Original line number Diff line number Diff line Loading @@ -42,63 +42,4 @@ std::string dispatchModeToString(int32_t dispatchMode) { return StringPrintf("%" PRId32, dispatchMode); } void InputTarget::addPointers(BitSet32 newPointerIds, float xOffset, float yOffset, float windowXScale, float windowYScale) { // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors // and non splittable windows since we will just use all the pointers from the input event. if (newPointerIds.isEmpty()) { setDefaultPointerInfo(xOffset, yOffset, windowXScale, windowYScale); return; } // Ensure that the new set of pointers doesn't overlap with the current set of pointers. ALOG_ASSERT((pointerIds & newPointerIds) == 0); pointerIds |= newPointerIds; while (!newPointerIds.isEmpty()) { int32_t pointerId = newPointerIds.clearFirstMarkedBit(); pointerInfos[pointerId].xOffset = xOffset; pointerInfos[pointerId].yOffset = yOffset; pointerInfos[pointerId].windowXScale = windowXScale; pointerInfos[pointerId].windowYScale = windowYScale; } } void InputTarget::setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, float windowYScale) { pointerIds.clear(); pointerInfos[0].xOffset = xOffset; pointerInfos[0].yOffset = yOffset; pointerInfos[0].windowXScale = windowXScale; pointerInfos[0].windowYScale = windowYScale; } bool InputTarget::useDefaultPointerInfo() const { return pointerIds.isEmpty(); } const PointerInfo& InputTarget::getDefaultPointerInfo() const { return pointerInfos[0]; } std::string InputTarget::getPointerInfoString() const { if (useDefaultPointerInfo()) { const PointerInfo& pointerInfo = getDefaultPointerInfo(); return StringPrintf("xOffset=%.1f, yOffset=%.1f windowScaleFactor=(%.1f, %.1f)", pointerInfo.xOffset, pointerInfo.yOffset, pointerInfo.windowXScale, pointerInfo.windowYScale); } std::string out; for (uint32_t i = pointerIds.firstMarkedBit(); i <= pointerIds.lastMarkedBit(); i++) { if (!pointerIds.hasBit(i)) { continue; } out += StringPrintf("\n pointerId %d: xOffset=%.1f, yOffset=%.1f " "windowScaleFactor=(%.1f, %.1f)", i, pointerInfos[i].xOffset, pointerInfos[i].yOffset, pointerInfos[i].windowXScale, pointerInfos[i].windowYScale); } return out; } } // namespace android::inputdispatcher
services/inputflinger/dispatcher/InputTarget.h +7 −40 Original line number Diff line number Diff line Loading @@ -23,22 +23,6 @@ namespace android::inputdispatcher { /* * Information about each pointer for an InputTarget. This includes offset and scale so * all pointers can be normalized to a single offset and scale. * * These values are ignored for KeyEvents */ struct PointerInfo { // The x and y offset to add to a MotionEvent as it is delivered. float xOffset = 0.0f; float yOffset = 0.0f; // Scaling factor to apply to MotionEvent as it is delivered. float windowXScale = 1.0f; float windowYScale = 1.0f; }; /* * An input target specifies how an input event is to be dispatched to a particular window * including the window's input channel, control flags, a timeout, and an X / Y offset to Loading Loading @@ -111,37 +95,20 @@ struct InputTarget { // Flags for the input target. int32_t flags = 0; // The x and y offset to add to a MotionEvent as it is delivered. // (ignored for KeyEvents) float xOffset = 0.0f; float yOffset = 0.0f; // Scaling factor to apply to MotionEvent as it is delivered. // (ignored for KeyEvents) float globalScaleFactor = 1.0f; float windowXScale = 1.0f; float windowYScale = 1.0f; // The subset of pointer ids to include in motion events dispatched to this input target // if FLAG_SPLIT is set. BitSet32 pointerIds; // The data is stored by the pointerId. Use the bit position of pointerIds to look up // PointerInfo per pointerId. PointerInfo pointerInfos[MAX_POINTERS]; void addPointers(BitSet32 pointerIds, float xOffset, float yOffset, float windowXScale, float windowYScale); void setDefaultPointerInfo(float xOffset, float yOffset, float windowXScale, float windowYScale); /** * Returns whether the default pointer information should be used. This will be true when the * InputTarget doesn't have any bits set in the pointerIds bitset. This can happen for monitors * and non splittable windows since we want all pointers for the EventEntry to go to this * target. */ bool useDefaultPointerInfo() const; /** * Returns the default PointerInfo object. This should be used when useDefaultPointerInfo is * true. */ const PointerInfo& getDefaultPointerInfo() const; std::string getPointerInfoString() const; }; std::string dispatchModeToString(int32_t dispatchMode); Loading
services/inputflinger/tests/InputDispatcher_test.cpp +0 −103 Original line number Diff line number Diff line Loading @@ -1571,107 +1571,4 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) { mWindow2->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); } TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) { mWindow1->setWindowScale(0.5f, 0.5f); // Touch Window 1 std::vector<PointF> touchedPoints = {PointF{10, 10}}; std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])}; NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints); // Touch Window 2 int32_t actionPointerDown = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); touchedPoints.emplace_back(PointF{150, 150}); expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1])); motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); // Consuming from window1 since it's the window that has the InputReceiver consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints); // Move both windows touchedPoints = {{20, 20}, {175, 175}}; expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]), getPointInWindow(mWindow2->getInfo(), touchedPoints[1])}; motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, touchedPoints); mDispatcher->notifyMotion(&motionArgs); consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints); } } // namespace android::inputdispatcher