diff options
author | 2022-11-09 13:42:06 -0800 | |
---|---|---|
committer | 2022-11-10 18:42:52 -0800 | |
commit | 253f464be4eec003d3b875f25a6318eca9b1c644 (patch) | |
tree | 24eaa0d02e09ac88bc9006d54ca98f846b0f2457 | |
parent | 6e1e987e52372f0d99fada08e74c7d5e068b6b53 (diff) |
Use ftl::Flags for InputTarget flags
These flags will now be type-safe.
Bug: 211379801
Test: m inputflinger_tests && adb sync data && adb shell -t /data/nativetest64/inputflinger_tests/inputflinger_tests
Change-Id: If1835151df74cfebf39ec3471f826082bea30e26
-rw-r--r-- | include/ftl/flags.h | 4 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/Entry.cpp | 3 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/Entry.h | 14 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 161 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 6 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputTarget.cpp | 18 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputTarget.h | 39 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/TouchState.cpp | 22 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/TouchState.h | 2 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/TouchedWindow.cpp | 6 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/TouchedWindow.h | 3 |
11 files changed, 136 insertions, 142 deletions
diff --git a/include/ftl/flags.h b/include/ftl/flags.h index 70aaa0e6dd..cdb4e840a4 100644 --- a/include/ftl/flags.h +++ b/include/ftl/flags.h @@ -125,7 +125,7 @@ public: /* Tests whether all of the given flags are set */ bool all(Flags<F> f) const { return (mFlags & f.mFlags) == f.mFlags; } - Flags<F> operator|(Flags<F> rhs) const { return static_cast<F>(mFlags | rhs.mFlags); } + constexpr Flags<F> operator|(Flags<F> rhs) const { return static_cast<F>(mFlags | rhs.mFlags); } Flags<F>& operator|=(Flags<F> rhs) { mFlags = mFlags | rhs.mFlags; return *this; @@ -217,7 +217,7 @@ inline Flags<F> operator~(F f) { } template <typename F, typename = std::enable_if_t<is_scoped_enum_v<F>>> -Flags<F> operator|(F lhs, F rhs) { +constexpr Flags<F> operator|(F lhs, F rhs) { return static_cast<F>(to_underlying(lhs) | to_underlying(rhs)); } diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 33e7e17ec0..ec9701ac24 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -308,7 +308,8 @@ std::string SensorEntry::getDescription() const { volatile int32_t DispatchEntry::sNextSeqAtomic; -DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags, +DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry, + ftl::Flags<InputTarget::Flags> targetFlags, const ui::Transform& transform, const ui::Transform& rawTransform, float globalScaleFactor) : seq(nextSeq()), diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 60f319a056..f8019126f3 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -223,7 +223,7 @@ struct DispatchEntry { const uint32_t seq; // unique sequence number, never 0 std::shared_ptr<EventEntry> eventEntry; // the event to dispatch - int32_t targetFlags; + ftl::Flags<InputTarget::Flags> targetFlags; ui::Transform transform; ui::Transform rawTransform; float globalScaleFactor; @@ -238,13 +238,15 @@ struct DispatchEntry { int32_t resolvedAction; int32_t resolvedFlags; - DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags, - const ui::Transform& transform, const ui::Transform& rawTransform, - float globalScaleFactor); + DispatchEntry(std::shared_ptr<EventEntry> eventEntry, + ftl::Flags<InputTarget::Flags> targetFlags, const ui::Transform& transform, + const ui::Transform& rawTransform, float globalScaleFactor); - inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } + inline bool hasForegroundTarget() const { + return targetFlags.test(InputTarget::Flags::FOREGROUND); + } - inline bool isSplit() const { return targetFlags & InputTarget::FLAG_SPLIT; } + inline bool isSplit() const { return targetFlags.test(InputTarget::Flags::SPLIT); } private: static volatile int32_t sNextSeqAtomic; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8ae59390c0..7b7c42a211 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -51,6 +51,7 @@ #define INDENT3 " " #define INDENT4 " " +using namespace android::ftl::flag_operators; using android::base::HwTimeoutMultiplier; using android::base::Result; using android::base::StringPrintf; @@ -242,9 +243,9 @@ std::string dumpQueue(const std::deque<DispatchEntry*>& queue, nsecs_t currentTi } dump.append(INDENT4); dump += entry.eventEntry->getDescription(); - dump += StringPrintf(", seq=%" PRIu32 - ", targetFlags=0x%08x, resolvedAction=%d, age=%" PRId64 "ms", - entry.seq, entry.targetFlags, entry.resolvedAction, + dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, resolvedAction=%d, age=%" PRId64 + "ms", + entry.seq, entry.targetFlags.string().c_str(), entry.resolvedAction, ns2ms(currentTime - entry.eventEntry->eventTime)); if (entry.deliveryTime != 0) { // This entry was delivered, so add information on how long we've been waiting @@ -289,9 +290,9 @@ bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) first->applicationInfo.token == second->applicationInfo.token; } -std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget, - std::shared_ptr<EventEntry> eventEntry, - int32_t inputTargetFlags) { +std::unique_ptr<DispatchEntry> createDispatchEntry( + const InputTarget& inputTarget, std::shared_ptr<EventEntry> eventEntry, + ftl::Flags<InputTarget::Flags> inputTargetFlags) { if (inputTarget.useDefaultPointerTransform()) { const ui::Transform& transform = inputTarget.getDefaultPointerTransform(); return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform, @@ -484,11 +485,11 @@ bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { entry.pointerProperties[pointerIndex].toolType == AMOTION_EVENT_TOOL_TYPE_ERASER); } -// Determines if the given window can be targeted as InputTarget::FLAG_FOREGROUND. +// Determines if the given window can be targeted as InputTarget::Flags::FOREGROUND. // Foreground events are only sent to "foreground targetable" windows, but not all gestures sent to // such window are necessarily targeted with the flag. For example, an event with ACTION_OUTSIDE can // be sent to such a window, but it is not a foreground event and doesn't use -// InputTarget::FLAG_FOREGROUND. +// InputTarget::Flags::FOREGROUND. bool canReceiveForegroundTouches(const WindowInfo& info) { // A non-touchable window can still receive touch events (e.g. in the case of // STYLUS_INTERCEPTOR), so prevent such windows from receiving foreground events for touches. @@ -1101,7 +1102,7 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayI if (addOutsideTargets && info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) { - touchState->addOrUpdateWindow(windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, + touchState->addOrUpdateWindow(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE, BitSet32(0)); } } @@ -1372,7 +1373,7 @@ void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, std::shared_ptr<F } InputTarget target; target.inputChannel = channel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; entry->dispatchInProgress = true; std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") + channel->getName(); @@ -1446,7 +1447,7 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked( } InputTarget target; target.inputChannel = channel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); @@ -1483,7 +1484,7 @@ std::vector<InputTarget> InputDispatcher::getInputTargetsFromWindowHandlesLocked } InputTarget target; target.inputChannel = channel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; inputTargets.push_back(target); } return inputTargets; @@ -1596,7 +1597,7 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<Key std::vector<InputTarget> inputTargets; addWindowTargetLocked(focusedWindow, - InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, + InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS, BitSet32(0), getDownTime(*entry), inputTargets); // Add monitor channels from event's or focused display. @@ -1709,7 +1710,8 @@ bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr< if (injectionResult == InputEventInjectionResult::SUCCEEDED) { LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr); addWindowTargetLocked(focusedWindow, - InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, + InputTarget::Flags::FOREGROUND | + InputTarget::Flags::DISPATCH_AS_IS, BitSet32(0), getDownTime(*entry), inputTargets); } } @@ -1761,7 +1763,7 @@ void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<Dr } InputTarget target; target.inputChannel = channel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; entry->dispatchInProgress = true; dispatchEventLocked(currentTime, entry, {target}); } @@ -2196,20 +2198,20 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } // Set target flags. - int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_IS; + ftl::Flags<InputTarget::Flags> targetFlags = InputTarget::Flags::DISPATCH_AS_IS; if (canReceiveForegroundTouches(*windowHandle->getInfo())) { // There should only be one touched window that can be "foreground" for the pointer. - targetFlags |= InputTarget::FLAG_FOREGROUND; + targetFlags |= InputTarget::Flags::FOREGROUND; } if (isSplit) { - targetFlags |= InputTarget::FLAG_SPLIT; + targetFlags |= InputTarget::Flags::SPLIT; } if (isWindowObscuredAtPointLocked(windowHandle, x, y)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; + targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED; } else if (isWindowObscuredLocked(windowHandle)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED; + targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; } // Update the temporary touch state. @@ -2276,7 +2278,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( } // Make a slippery exit from the old window. tempTouchState.addOrUpdateWindow(oldTouchedWindowHandle, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, + InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0)); // Make a slippery entrance into the new window. @@ -2284,17 +2286,18 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( isSplit = !isFromMouse; } - int32_t targetFlags = InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER; + ftl::Flags<InputTarget::Flags> targetFlags = + InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER; if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) { - targetFlags |= InputTarget::FLAG_FOREGROUND; + targetFlags |= InputTarget::Flags::FOREGROUND; } if (isSplit) { - targetFlags |= InputTarget::FLAG_SPLIT; + targetFlags |= InputTarget::Flags::SPLIT; } if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; + targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED; } else if (isWindowObscuredLocked(newTouchedWindowHandle)) { - targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED; + targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED; } BitSet32 pointerIds; @@ -2317,7 +2320,8 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( mLastHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(mLastHoverWindowHandle, - InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0)); + InputTarget::Flags::DISPATCH_AS_HOVER_EXIT, + BitSet32(0)); } // Let the new window know that the hover sequence is starting, unless we already did it @@ -2330,7 +2334,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( newHoverWindowHandle->getName().c_str()); } tempTouchState.addOrUpdateWindow(newHoverWindowHandle, - InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, + InputTarget::Flags::DISPATCH_AS_HOVER_ENTER, BitSet32(0)); } } @@ -2343,7 +2347,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( [](const TouchedWindow& touchedWindow) { return !canReceiveForegroundTouches( *touchedWindow.windowHandle->getInfo()) || - (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0; + touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND); })) { ALOGI("Dropping event because there is no touched window on display %d to receive it: %s", displayId, entry.getDescription().c_str()); @@ -2355,7 +2359,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( if (entry.injectionState != nullptr) { std::string errs; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { - if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { + if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) { // Allow ACTION_OUTSIDE events generated by targeted injection to be // dispatched to any uid, since the coords will be zeroed out later. continue; @@ -2380,11 +2384,11 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( if (foregroundWindowHandle) { const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid; for (const TouchedWindow& touchedWindow : tempTouchState.windows) { - if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { + if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) { sp<WindowInfoHandle> windowInfoHandle = touchedWindow.windowHandle; if (windowInfoHandle->getInfo()->ownerUid != foregroundWindowUid) { tempTouchState.addOrUpdateWindow(windowInfoHandle, - InputTarget::FLAG_ZERO_COORDS, + InputTarget::Flags::ZERO_COORDS, BitSet32(0)); } } @@ -2411,13 +2415,12 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( if (info->displayId == displayId && windowHandle->getInfo()->inputConfig.test( WindowInfo::InputConfig::IS_WALLPAPER)) { - tempTouchState - .addOrUpdateWindow(windowHandle, - InputTarget::FLAG_WINDOW_IS_OBSCURED | - InputTarget:: - FLAG_WINDOW_IS_PARTIALLY_OBSCURED | - InputTarget::FLAG_DISPATCH_AS_IS, - BitSet32(0), entry.eventTime); + tempTouchState.addOrUpdateWindow(windowHandle, + InputTarget::Flags::WINDOW_IS_OBSCURED | + InputTarget::Flags:: + WINDOW_IS_PARTIALLY_OBSCURED | + InputTarget::Flags::DISPATCH_AS_IS, + BitSet32(0), entry.eventTime); } } } @@ -2608,7 +2611,8 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { } void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds, + ftl::Flags<InputTarget::Flags> targetFlags, + BitSet32 pointerIds, std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const { std::vector<InputTarget>::iterator it = @@ -2656,7 +2660,7 @@ void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) { InputTarget target; target.inputChannel = monitor.inputChannel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; // target.firstDownTimeInTarget is not set for global monitors. It is only required in split // touch and global monitoring works as intended even without setting firstDownTimeInTarget if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { @@ -2688,7 +2692,7 @@ static bool canBeObscuredBy(const sp<WindowInfoHandle>& windowHandle, // We do want to potentially flag touchable windows even if they have 0 // opacity, since they can consume touches and alter the effects of the // user interaction (eg. apps that rely on - // FLAG_WINDOW_IS_PARTIALLY_OBSCURED should still be told about those + // Flags::WINDOW_IS_PARTIALLY_OBSCURED should still be told about those // windows), hence we also check for FLAG_NOT_TOUCHABLE. return false; } else if (info->ownerUid == otherInfo->ownerUid) { @@ -2917,9 +2921,9 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, ATRACE_NAME(message.c_str()); } if (DEBUG_DISPATCH_CYCLE) { - ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, " + ALOGD("channel '%s' ~ prepareDispatchCycle - flags=%s, " "globalScaleFactor=%f, pointerIds=0x%x %s", - connection->getInputChannelName().c_str(), inputTarget.flags, + connection->getInputChannelName().c_str(), inputTarget.flags.string().c_str(), inputTarget.globalScaleFactor, inputTarget.pointerIds.value, inputTarget.getPointerInfoString().c_str()); } @@ -2936,9 +2940,9 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, } // Split a motion event if needed. - if (inputTarget.flags & InputTarget::FLAG_SPLIT) { + if (inputTarget.flags.test(InputTarget::Flags::SPLIT)) { LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION, - "Entry type %s should not have FLAG_SPLIT", + "Entry type %s should not have Flags::SPLIT", ftl::enum_string(eventEntry->type).c_str()); const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry); @@ -2987,17 +2991,17 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, // Enqueue dispatch entries for the requested modes. enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); + InputTarget::Flags::DISPATCH_AS_HOVER_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_OUTSIDE); + InputTarget::Flags::DISPATCH_AS_OUTSIDE); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER); + InputTarget::Flags::DISPATCH_AS_HOVER_ENTER); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_IS); + InputTarget::Flags::DISPATCH_AS_IS); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT); + InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, - InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER); + InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER); // If the outbound queue was previously empty, start the dispatch cycle going. if (wasEmpty && !connection->outboundQueue.empty()) { @@ -3008,18 +3012,20 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection, std::shared_ptr<EventEntry> eventEntry, const InputTarget& inputTarget, - int32_t dispatchMode) { + ftl::Flags<InputTarget::Flags> dispatchMode) { if (ATRACE_ENABLED()) { std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)", connection->getInputChannelName().c_str(), - dispatchModeToString(dispatchMode).c_str()); + dispatchMode.string().c_str()); ATRACE_NAME(message.c_str()); } - int32_t inputTargetFlags = inputTarget.flags; - if (!(inputTargetFlags & dispatchMode)) { + ftl::Flags<InputTarget::Flags> inputTargetFlags = inputTarget.flags; + if (!inputTargetFlags.any(dispatchMode)) { return; } - inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode; + + inputTargetFlags.clear(InputTarget::DISPATCH_MASK); + inputTargetFlags |= dispatchMode; // This is a new event. // Enqueue a new dispatch entry onto the outbound queue for this connection. @@ -3056,15 +3062,15 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio constexpr int32_t DEFAULT_RESOLVED_EVENT_ID = static_cast<int32_t>(IdGenerator::Source::OTHER); dispatchEntry->resolvedEventId = DEFAULT_RESOLVED_EVENT_ID; - if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { + if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) { + } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) { + } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { + } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL; - } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) { + } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) { dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN; } else { dispatchEntry->resolvedAction = motionEntry.action; @@ -3084,10 +3090,10 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio } dispatchEntry->resolvedFlags = motionEntry.flags; - if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) { + if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) { dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; } - if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) { + if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) { dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED; } @@ -3187,8 +3193,7 @@ void InputDispatcher::updateInteractionTokensLocked(const EventEntry& entry, std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens; std::vector<sp<Connection>> newConnections; for (const InputTarget& target : targets) { - if ((target.flags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) == - InputTarget::FLAG_DISPATCH_AS_OUTSIDE) { + if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) { continue; // Skip windows that receive ACTION_OUTSIDE } @@ -3247,7 +3252,7 @@ status_t InputDispatcher::publishMotionEvent(Connection& connection, // Set the X and Y offset and X and Y scale depending on the input source. if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) && - !(dispatchEntry.targetFlags & InputTarget::FLAG_ZERO_COORDS)) { + !(dispatchEntry.targetFlags.test(InputTarget::Flags::ZERO_COORDS))) { float globalScaleFactor = dispatchEntry.globalScaleFactor; if (globalScaleFactor != 1.0f) { for (uint32_t i = 0; i < motionEntry.pointerCount; i++) { @@ -3260,7 +3265,7 @@ status_t InputDispatcher::publishMotionEvent(Connection& connection, } usingCoords = scaledCoords; } - } else if (dispatchEntry.targetFlags & InputTarget::FLAG_ZERO_COORDS) { + } else if (dispatchEntry.targetFlags.test(InputTarget::Flags::ZERO_COORDS)) { // We don't want the dispatch target to know the coordinates for (uint32_t i = 0; i < motionEntry.pointerCount; i++) { scaledCoords[i].clear(); @@ -3662,7 +3667,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( target.globalScaleFactor = windowInfo->globalScaleFactor; } target.inputChannel = connection->inputChannel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; const bool wasEmpty = connection->outboundQueue.empty(); @@ -3697,7 +3702,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( } enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), target, - InputTarget::FLAG_DISPATCH_AS_IS); + InputTarget::Flags::DISPATCH_AS_IS); } // If the outbound queue was previously empty, start the dispatch cycle going. @@ -3733,7 +3738,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( target.globalScaleFactor = windowInfo->globalScaleFactor; } target.inputChannel = connection->inputChannel; - target.flags = InputTarget::FLAG_DISPATCH_AS_IS; + target.flags = InputTarget::Flags::DISPATCH_AS_IS; const bool wasEmpty = connection->outboundQueue.empty(); for (std::unique_ptr<EventEntry>& downEventEntry : downEvents) { @@ -3759,7 +3764,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( } enqueueDispatchEntryLocked(connection, std::move(downEventEntry), target, - InputTarget::FLAG_DISPATCH_AS_IS); + InputTarget::Flags::DISPATCH_AS_IS); } // If the outbound queue was previously empty, start the dispatch cycle going. @@ -4822,7 +4827,7 @@ void InputDispatcher::setInputWindowsLocked( synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel, options); // Since we are about to drop the touch, cancel the events for the wallpaper as // well. - if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND && + if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) && touchedWindow.windowHandle->getInfo()->inputConfig.test( gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) { sp<WindowInfoHandle> wallpaper = state.getWallpaperWindow(); @@ -5140,16 +5145,16 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< } // Erase old window. - int32_t oldTargetFlags = touchedWindow->targetFlags; + ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags; BitSet32 pointerIds = touchedWindow->pointerIds; state->removeWindowByToken(fromToken); // Add new window. nsecs_t downTimeInTarget = now(); - int32_t newTargetFlags = - oldTargetFlags & (InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS); + ftl::Flags<InputTarget::Flags> newTargetFlags = + oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS); if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) { - newTargetFlags |= InputTarget::FLAG_FOREGROUND; + newTargetFlags |= InputTarget::Flags::FOREGROUND; } state->addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds, downTimeInTarget); @@ -5203,7 +5208,7 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindowLocked(int32_t sp<WindowInfoHandle> touchedForegroundWindow; // If multiple foreground windows are touched, return nullptr for (const TouchedWindow& window : state.windows) { - if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { + if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) { if (touchedForegroundWindow != nullptr) { ALOGI("Two or more foreground windows: %s and %s", touchedForegroundWindow->getName().c_str(), diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 0ddbbeb27e..5efb39e0f2 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -553,7 +553,7 @@ private: const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock); void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds, + ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId) @@ -600,8 +600,8 @@ private: std::shared_ptr<EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock); void enqueueDispatchEntryLocked(const sp<Connection>& connection, std::shared_ptr<EventEntry>, - const InputTarget& inputTarget, int32_t dispatchMode) - REQUIRES(mLock); + const InputTarget& inputTarget, + ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock); status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const; void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp index 2df97d9a12..2f39480555 100644 --- a/services/inputflinger/dispatcher/InputTarget.cpp +++ b/services/inputflinger/dispatcher/InputTarget.cpp @@ -24,24 +24,6 @@ using android::base::StringPrintf; namespace android::inputdispatcher { -std::string dispatchModeToString(int32_t dispatchMode) { - switch (dispatchMode) { - case InputTarget::FLAG_DISPATCH_AS_IS: - return "DISPATCH_AS_IS"; - case InputTarget::FLAG_DISPATCH_AS_OUTSIDE: - return "DISPATCH_AS_OUTSIDE"; - case InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER: - return "DISPATCH_AS_HOVER_ENTER"; - case InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT: - return "DISPATCH_AS_HOVER_EXIT"; - case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT: - return "DISPATCH_AS_SLIPPERY_EXIT"; - case InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER: - return "DISPATCH_AS_SLIPPERY_ENTER"; - } - return StringPrintf("%" PRId32, dispatchMode); -} - void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) { // The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no // valid pointer property from the input event. diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index b2966f680c..61b07feb3a 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -16,6 +16,7 @@ #pragma once +#include <ftl/flags.h> #include <gui/constants.h> #include <input/InputTransport.h> #include <ui/Transform.h> @@ -30,70 +31,70 @@ namespace android::inputdispatcher { * window area. */ struct InputTarget { - enum { + enum class Flags : uint32_t { /* This flag indicates that the event is being delivered to a foreground application. */ - FLAG_FOREGROUND = 1 << 0, + FOREGROUND = 1 << 0, /* This flag indicates that the MotionEvent falls within the area of the target * obscured by another visible window above it. The motion event should be * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */ - FLAG_WINDOW_IS_OBSCURED = 1 << 1, + WINDOW_IS_OBSCURED = 1 << 1, /* This flag indicates that a motion event is being split across multiple windows. */ - FLAG_SPLIT = 1 << 2, + SPLIT = 1 << 2, /* This flag indicates that the pointer coordinates dispatched to the application * will be zeroed out to avoid revealing information to an application. This is * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing * the same UID from watching all touches. */ - FLAG_ZERO_COORDS = 1 << 3, + ZERO_COORDS = 1 << 3, /* This flag indicates that the event should be sent as is. * Should always be set unless the event is to be transmuted. */ - FLAG_DISPATCH_AS_IS = 1 << 8, + DISPATCH_AS_IS = 1 << 8, /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside * of the area of this target and so should instead be delivered as an * AMOTION_EVENT_ACTION_OUTSIDE to this target. */ - FLAG_DISPATCH_AS_OUTSIDE = 1 << 9, + DISPATCH_AS_OUTSIDE = 1 << 9, /* This flag indicates that a hover sequence is starting in the given window. * The event is transmuted into ACTION_HOVER_ENTER. */ - FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10, + DISPATCH_AS_HOVER_ENTER = 1 << 10, /* This flag indicates that a hover event happened outside of a window which handled * previous hover events, signifying the end of the current hover sequence for that * window. * The event is transmuted into ACTION_HOVER_ENTER. */ - FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11, + DISPATCH_AS_HOVER_EXIT = 1 << 11, /* This flag indicates that the event should be canceled. * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips * outside of a window. */ - FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12, + DISPATCH_AS_SLIPPERY_EXIT = 1 << 12, /* This flag indicates that the event should be dispatched as an initial down. * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips * into a new window. */ - FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13, - - /* Mask for all dispatch modes. */ - FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS | FLAG_DISPATCH_AS_OUTSIDE | - FLAG_DISPATCH_AS_HOVER_ENTER | FLAG_DISPATCH_AS_HOVER_EXIT | - FLAG_DISPATCH_AS_SLIPPERY_EXIT | FLAG_DISPATCH_AS_SLIPPERY_ENTER, + DISPATCH_AS_SLIPPERY_ENTER = 1 << 13, /* This flag indicates that the target of a MotionEvent is partly or wholly * obscured by another visible window above it. The motion event should be * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */ - FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14, - + WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14, }; + /* Mask for all dispatch modes. */ + static constexpr const ftl::Flags<InputTarget::Flags> DISPATCH_MASK = + ftl::Flags<InputTarget::Flags>() | Flags::DISPATCH_AS_IS | Flags::DISPATCH_AS_OUTSIDE | + Flags::DISPATCH_AS_HOVER_ENTER | Flags::DISPATCH_AS_HOVER_EXIT | + Flags::DISPATCH_AS_SLIPPERY_EXIT | Flags::DISPATCH_AS_SLIPPERY_ENTER; + // The input channel to be targeted. std::shared_ptr<InputChannel> inputChannel; // Flags for the input target. - int32_t flags = 0; + ftl::Flags<Flags> flags; // Scaling factor to apply to MotionEvent as it is delivered. // (ignored for KeyEvents) diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp index 0cc2c6da9b..ee7da93975 100644 --- a/services/inputflinger/dispatcher/TouchState.cpp +++ b/services/inputflinger/dispatcher/TouchState.cpp @@ -20,6 +20,7 @@ #include "InputTarget.h" #include "TouchState.h" +using namespace android::ftl::flag_operators; using android::base::StringPrintf; using android::gui::WindowInfo; using android::gui::WindowInfoHandle; @@ -30,14 +31,15 @@ void TouchState::reset() { *this = TouchState(); } -void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags, - BitSet32 pointerIds, std::optional<nsecs_t> eventTime) { +void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, + ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, + std::optional<nsecs_t> eventTime) { for (size_t i = 0; i < windows.size(); i++) { TouchedWindow& touchedWindow = windows[i]; if (touchedWindow.windowHandle == windowHandle) { touchedWindow.targetFlags |= targetFlags; - if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) { - touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS; + if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) { + touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS); } // 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 an pointer is down for @@ -70,10 +72,10 @@ void TouchState::removeWindowByToken(const sp<IBinder>& token) { void TouchState::filterNonAsIsTouchWindows() { for (size_t i = 0; i < windows.size();) { TouchedWindow& window = windows[i]; - if (window.targetFlags & - (InputTarget::FLAG_DISPATCH_AS_IS | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) { - window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK; - window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS; + if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS | + InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) { + window.targetFlags.clear(InputTarget::DISPATCH_MASK); + window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS; i += 1; } else { windows.erase(windows.begin() + i); @@ -105,7 +107,7 @@ void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle() const { for (size_t i = 0; i < windows.size(); i++) { const TouchedWindow& window = windows[i]; - if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { + if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) { return window.windowHandle; } } @@ -116,7 +118,7 @@ bool TouchState::isSlippery() const { // Must have exactly one foreground window. bool haveSlipperyForegroundWindow = false; for (const TouchedWindow& window : windows) { - if (window.targetFlags & InputTarget::FLAG_FOREGROUND) { + if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) { if (haveSlipperyForegroundWindow || !window.windowHandle->getInfo()->inputConfig.test( WindowInfo::InputConfig::SLIPPERY)) { diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h index e4e59fd132..77c1cdf50a 100644 --- a/services/inputflinger/dispatcher/TouchState.h +++ b/services/inputflinger/dispatcher/TouchState.h @@ -40,7 +40,7 @@ struct TouchState { void reset(); void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle, - int32_t targetFlags, BitSet32 pointerIds, + ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds, std::optional<nsecs_t> eventTime = std::nullopt); void removeWindowByToken(const sp<IBinder>& token); void filterNonAsIsTouchWindows(); diff --git a/services/inputflinger/dispatcher/TouchedWindow.cpp b/services/inputflinger/dispatcher/TouchedWindow.cpp index ec51662abb..af745988ad 100644 --- a/services/inputflinger/dispatcher/TouchedWindow.cpp +++ b/services/inputflinger/dispatcher/TouchedWindow.cpp @@ -27,9 +27,9 @@ namespace inputdispatcher { std::string TouchedWindow::dump() const { return StringPrintf("name='%s', pointerIds=0x%0x, " - "targetFlags=0x%x, firstDownTimeInTarget=%s\n", - windowHandle->getName().c_str(), pointerIds.value, targetFlags, - toString(firstDownTimeInTarget).c_str()); + "targetFlags=%s, firstDownTimeInTarget=%s\n", + windowHandle->getName().c_str(), pointerIds.value, + targetFlags.string().c_str(), toString(firstDownTimeInTarget).c_str()); } } // namespace inputdispatcher diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h index 0cc99999d0..dd08323dd4 100644 --- a/services/inputflinger/dispatcher/TouchedWindow.h +++ b/services/inputflinger/dispatcher/TouchedWindow.h @@ -18,6 +18,7 @@ #include <gui/WindowInfo.h> #include <utils/BitSet.h> +#include "InputTarget.h" namespace android { @@ -26,7 +27,7 @@ namespace inputdispatcher { // Focus tracking for touch. struct TouchedWindow { sp<gui::WindowInfoHandle> windowHandle; - int32_t targetFlags; + ftl::Flags<InputTarget::Flags> targetFlags; BitSet32 pointerIds; bool isPilferingPointers = false; // Time at which the first action down occurred on this window. |