Revert "[8/n InputDispatcher refactor] move input connections to a subclass"

This reverts commit 49586f42902d3599abaca7bc5c933177122de507.

Reason for revert: b/389067592

Change-Id: Iccaf60f7143a337e055d43170b16543f41163360
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index ae4a34a..fcd784d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -928,7 +928,6 @@
 InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                  std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
       : mPolicy(policy),
-        mLooper(sp<Looper>::make(false)),
         mPendingEvent(nullptr),
         mLastDropReason(DropReason::NOT_DROPPED),
         mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
@@ -939,7 +938,6 @@
         mDispatchFrozen(false),
         mInputFilterEnabled(false),
         mMaximumObscuringOpacityForTouch(1.0f),
-        mConnectionManager(mLooper),
         mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT),
         mWindowTokenWithPointerCapture(nullptr),
         mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID),
@@ -950,6 +948,7 @@
                         : std::move(std::unique_ptr<InputEventTimelineProcessor>(
                                   new LatencyAggregator()))),
         mLatencyTracker(*mInputEventTimelineProcessor) {
+    mLooper = sp<Looper>::make(false);
     mReporter = createInputReporter();
 
     mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
@@ -972,6 +971,11 @@
     releasePendingEventLocked();
     drainInboundQueueLocked();
     mCommandQueue.clear();
+
+    while (!mConnectionsByToken.empty()) {
+        std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
+        removeInputChannelLocked(connection, /*notify=*/false);
+    }
 }
 
 status_t InputDispatcher::start() {
@@ -1088,8 +1092,7 @@
     }
 
     // If we reached here, we have an unresponsive connection.
-    std::shared_ptr<Connection> connection =
-            mConnectionManager.getConnection(mAnrTracker.firstToken());
+    std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
     if (connection == nullptr) {
         ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
         return nextAnrCheck;
@@ -1341,7 +1344,7 @@
                                                      motionEntry.deviceId, mTouchStatesByDisplay);
         for (const auto& windowHandle : touchedSpies) {
             const std::shared_ptr<Connection> connection =
-                    mConnectionManager.getConnection(windowHandle->getToken());
+                    getConnectionLocked(windowHandle->getToken());
             if (connection != nullptr && connection->responsive) {
                 // This spy window could take more input. Drop all events preceding this
                 // event, so that the spy window can get a chance to receive the stream.
@@ -1724,8 +1727,7 @@
 
 void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime,
                                           std::shared_ptr<const FocusEntry> entry) {
-    std::shared_ptr<Connection> connection =
-            mConnectionManager.getConnection(entry->connectionToken);
+    std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
     if (connection == nullptr) {
         return; // Connection has gone away
     }
@@ -1793,7 +1795,7 @@
         }
     }
 
-    auto connection = mConnectionManager.getConnection(token);
+    auto connection = getConnectionLocked(token);
     if (connection == nullptr) {
         // Window has gone away, clean up Pointer Capture state.
         mWindowTokenWithPointerCapture = nullptr;
@@ -1832,7 +1834,7 @@
         if (token == nullptr) {
             continue;
         }
-        std::shared_ptr<Connection> connection = mConnectionManager.getConnection(token);
+        std::shared_ptr<Connection> connection = getConnectionLocked(token);
         if (connection == nullptr) {
             continue; // Connection has gone away
         }
@@ -1956,8 +1958,7 @@
                           InputTarget::Flags::FOREGROUND, getDownTime(*entry), inputTargets);
 
     // Add monitor channels from event's or focused display.
-    ui::LogicalDisplayId displayId = getTargetDisplayId(*entry);
-    addGlobalMonitoringTargetsLocked(inputTargets, displayId);
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
 
     if (mTracer) {
         ensureEventTraced(*entry);
@@ -2099,8 +2100,7 @@
     }
 
     // Add monitor channels from event's or focused display.
-    ui::LogicalDisplayId displayId = getTargetDisplayId(*entry);
-    addGlobalMonitoringTargetsLocked(inputTargets, displayId);
+    addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
 
     if (mTracer) {
         ensureEventTraced(*entry);
@@ -2127,8 +2127,7 @@
 
 void InputDispatcher::dispatchDragLocked(nsecs_t currentTime,
                                          std::shared_ptr<const DragEntry> entry) {
-    std::shared_ptr<Connection> connection =
-            mConnectionManager.getConnection(entry->connectionToken);
+    std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
     if (connection == nullptr) {
         return; // Connection has gone away
     }
@@ -2372,6 +2371,26 @@
     return focusedWindowHandle;
 }
 
+/**
+ * Given a list of monitors, remove the ones we cannot find a connection for, and the ones
+ * that are currently unresponsive.
+ */
+std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
+        const std::vector<Monitor>& monitors) const {
+    std::vector<Monitor> responsiveMonitors;
+    std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
+                 [](const Monitor& monitor) REQUIRES(mLock) {
+                     std::shared_ptr<Connection> connection = monitor.connection;
+                     if (!connection->responsive) {
+                         ALOGW("Unresponsive monitor %s will not get the new gesture",
+                               connection->getInputChannelName().c_str());
+                         return false;
+                     }
+                     return true;
+                 });
+    return responsiveMonitors;
+}
+
 base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
 InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
     ATRACE_CALL();
@@ -2922,8 +2941,7 @@
     const WindowInfo* windowInfo = windowHandle->getInfo();
 
     if (it == inputTargets.end()) {
-        std::shared_ptr<Connection> connection =
-                mConnectionManager.getConnection(windowHandle->getToken());
+        std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
         if (connection == nullptr) {
             ALOGW("Not creating InputTarget for %s, no input channel",
                   windowHandle->getName().c_str());
@@ -2977,8 +2995,7 @@
     const WindowInfo* windowInfo = windowHandle->getInfo();
 
     if (it == inputTargets.end()) {
-        std::shared_ptr<Connection> connection =
-                mConnectionManager.getConnection(windowHandle->getToken());
+        std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
         if (connection == nullptr) {
             ALOGW("Not creating InputTarget for %s, no input channel",
                   windowHandle->getName().c_str());
@@ -3013,31 +3030,18 @@
 
 void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
                                                        ui::LogicalDisplayId displayId) {
-    ui::Transform displayTransform = mWindowInfos.getDisplayTransform(displayId);
-    mConnectionManager
-            .forEachGlobalMonitorConnection(displayId,
-                                            [&](const std::shared_ptr<Connection>& connection) {
-                                                if (!connection->responsive) {
-                                                    ALOGW("Ignoring unrsponsive monitor: %s",
-                                                          connection->getInputChannelName()
-                                                                  .c_str());
-                                                    return;
-                                                }
+    auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
+    if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
 
-                                                InputTarget target{connection};
-                                                // 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. Since
-                                                // global monitors don't have windows, use the
-                                                // display transform as the raw transform.
-                                                base::ScopedLockAssertion assumeLocked(mLock);
-                                                target.rawTransform =
-                                                        mWindowInfos.getDisplayTransform(displayId);
-                                                target.setDefaultPointerTransform(
-                                                        target.rawTransform);
-                                                inputTargets.push_back(target);
-                                            });
+    for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
+        InputTarget target{monitor.connection};
+        // 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.
+        // Since global monitors don't have windows, use the display transform as the raw transform.
+        target.rawTransform = mWindowInfos.getDisplayTransform(displayId);
+        target.setDefaultPointerTransform(target.rawTransform);
+        inputTargets.push_back(target);
+    }
 }
 
 /**
@@ -3996,7 +4000,7 @@
 
 int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
     std::scoped_lock _l(mLock);
-    std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
+    std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
     if (connection == nullptr) {
         ALOGW("Received looper callback for unknown input channel token %p.  events=0x%x",
               connectionToken.get(), events);
@@ -4104,12 +4108,12 @@
 
 void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
         const CancelationOptions& options) {
-    mConnectionManager.forEachGlobalMonitorConnection(
-            [&](const std::shared_ptr<Connection>& connection) {
-                base::ScopedLockAssertion assumeLocked(mLock);
-                synthesizeCancelationEventsForConnectionLocked(connection, options,
-                                                               /*window=*/nullptr);
-            });
+    for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
+        for (const Monitor& monitor : monitors) {
+            synthesizeCancelationEventsForConnectionLocked(monitor.connection, options,
+                                                           /*window=*/nullptr);
+        }
+    }
 }
 
 void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
@@ -4127,7 +4131,7 @@
     }
 
     std::shared_ptr<Connection> resolvedConnection =
-            connection ? connection : mConnectionManager.getConnection(windowHandle->getToken());
+            connection ? connection : getConnectionLocked(windowHandle->getToken());
     if (!resolvedConnection) {
         LOG(DEBUG) << __func__ << "No connection found for window: " << windowHandle->getName();
         return;
@@ -5292,7 +5296,7 @@
         return false;
     }
 
-    std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken());
+    std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken());
     if (connection == nullptr) {
         ALOGW("Not sending touch to %s because there's no corresponding connection",
               window->getName().c_str());
@@ -5355,7 +5359,7 @@
     std::vector<sp<WindowInfoHandle>> newHandles;
     for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
         const WindowInfo* info = handle->getInfo();
-        if (mConnectionManager.getConnection(handle->getToken()) == nullptr) {
+        if (getConnectionLocked(handle->getToken()) == nullptr) {
             const bool noInputChannel =
                     info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
             const bool canReceiveInput =
@@ -5861,8 +5865,8 @@
 
         // Synthesize cancel for old window and down for new window.
         ScopedSyntheticEventTracer traceContext(mTracer);
-        std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
-        std::shared_ptr<Connection> toConnection = mConnectionManager.getConnection(toToken);
+        std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken);
+        std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
         if (fromConnection != nullptr && toConnection != nullptr) {
             fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
             CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
@@ -6037,9 +6041,17 @@
 
     dump += addLinePrefix(mWindowInfos.dumpDisplayAndWindowInfo(), INDENT);
 
-    const nsecs_t currentTime = now();
+    if (!mGlobalMonitorsByDisplay.empty()) {
+        for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
+            dump += StringPrintf(INDENT "Global monitors on display %s:\n",
+                                 displayId.toString().c_str());
+            dumpMonitors(dump, monitors);
+        }
+    } else {
+        dump += INDENT "Global Monitors: <none>\n";
+    }
 
-    dump += addLinePrefix(mConnectionManager.dump(currentTime), INDENT);
+    const nsecs_t currentTime = now();
 
     // Dump recently dispatched or dropped events from oldest to newest.
     if (!mRecentQueue.empty()) {
@@ -6082,6 +6094,37 @@
         dump += INDENT "CommandQueue: <empty>\n";
     }
 
+    if (!mConnectionsByToken.empty()) {
+        dump += INDENT "Connections:\n";
+        for (const auto& [token, connection] : mConnectionsByToken) {
+            dump += StringPrintf(INDENT2 "%i: channelName='%s', "
+                                         "status=%s, monitor=%s, responsive=%s\n",
+                                 connection->inputPublisher.getChannel().getFd(),
+                                 connection->getInputChannelName().c_str(),
+                                 ftl::enum_string(connection->status).c_str(),
+                                 toString(connection->monitor), toString(connection->responsive));
+
+            if (!connection->outboundQueue.empty()) {
+                dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n",
+                                     connection->outboundQueue.size());
+                dump += dumpQueue(connection->outboundQueue, currentTime);
+            }
+
+            if (!connection->waitQueue.empty()) {
+                dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n",
+                                     connection->waitQueue.size());
+                dump += dumpQueue(connection->waitQueue, currentTime);
+            }
+            std::string inputStateDump = streamableToString(connection->inputState);
+            if (!inputStateDump.empty()) {
+                dump += INDENT3 "InputState: ";
+                dump += inputStateDump + "\n";
+            }
+        }
+    } else {
+        dump += INDENT "Connections: <none>\n";
+    }
+
     if (!mTouchModePerDisplay.empty()) {
         dump += INDENT "TouchModePerDisplay:\n";
         for (const auto& [displayId, touchMode] : mTouchModePerDisplay) {
@@ -6102,6 +6145,16 @@
     dump += mTracer == nullptr ? "Disabled" : "Enabled";
 }
 
+void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const {
+    const size_t numMonitors = monitors.size();
+    for (size_t i = 0; i < numMonitors; i++) {
+        const Monitor& monitor = monitors[i];
+        const std::shared_ptr<Connection>& connection = monitor.connection;
+        dump += StringPrintf(INDENT2 "%zu: '%s', ", i, connection->getInputChannelName().c_str());
+        dump += "\n";
+    }
+}
+
 class LooperEventCallback : public LooperCallback {
 public:
     LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {}
@@ -6128,8 +6181,14 @@
         std::scoped_lock _l(mLock);
         const sp<IBinder>& token = serverChannel->getConnectionToken();
         const int fd = serverChannel->getFd();
+        std::shared_ptr<Connection> connection =
+                std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
+                                             mIdGenerator);
 
-        mConnectionManager.createConnection(std::move(serverChannel), mIdGenerator);
+        auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
+        if (!inserted) {
+            ALOGE("Created a new connection, but the token %p is already known", token.get());
+        }
 
         std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                             this, std::placeholders::_1, token);
@@ -6162,11 +6221,19 @@
 
         const sp<IBinder>& token = serverChannel->getConnectionToken();
         const int fd = serverChannel->getFd();
+        std::shared_ptr<Connection> connection =
+                std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/true,
+                                             mIdGenerator);
+
+        auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
+        if (!inserted) {
+            ALOGE("Created a new connection, but the token %p is already known", token.get());
+        }
+
         std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                             this, std::placeholders::_1, token);
 
-        mConnectionManager.createGlobalInputMonitor(displayId, std::move(serverChannel),
-                                                    mIdGenerator, pid);
+        mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
 
         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
                        nullptr);
@@ -6180,14 +6247,14 @@
 status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) {
     { // acquire lock
         std::scoped_lock _l(mLock);
-        std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
+        std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
         if (connection == nullptr) {
             // Connection can be removed via socket hang up or an explicit call to
             // 'removeInputChannel'
             return BAD_VALUE;
         }
 
-        status_t status = mConnectionManager.removeInputChannel(connection);
+        status_t status = removeInputChannelLocked(connection, /*notify=*/false);
         if (status) {
             return status;
         }
@@ -6203,14 +6270,19 @@
                                                    bool notify) {
     LOG_ALWAYS_FATAL_IF(connection == nullptr);
     abortBrokenDispatchCycleLocked(connection, notify);
+    removeConnectionLocked(connection);
 
-    mAnrTracker.eraseToken(connection->getToken());
-    mConnectionManager.removeInputChannel(connection);
+    if (connection->monitor) {
+        removeMonitorChannelLocked(connection->getToken());
+    }
 
+    mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
+
+    connection->status = Connection::Status::ZOMBIE;
     return OK;
 }
 
-void InputDispatcher::ConnectionManager::removeMonitorChannel(const sp<IBinder>& connectionToken) {
+void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) {
     for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) {
         auto& [displayId, monitors] = *it;
         std::erase_if(monitors, [connectionToken](const Monitor& monitor) {
@@ -6231,8 +6303,7 @@
 }
 
 status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
-    const std::shared_ptr<Connection> requestingConnection =
-            mConnectionManager.getConnection(token);
+    const std::shared_ptr<Connection> requestingConnection = getConnectionLocked(token);
     if (!requestingConnection) {
         LOG(WARNING)
                 << "Attempted to pilfer pointers from an un-registered channel or invalid token";
@@ -6339,8 +6410,7 @@
     } // release lock
 }
 
-std::optional<gui::Pid> InputDispatcher::ConnectionManager::findMonitorPidByToken(
-        const sp<IBinder>& token) const {
+std::optional<gui::Pid> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) {
     for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
         for (const Monitor& monitor : monitors) {
             if (monitor.connection->getToken() == token) {
@@ -6351,7 +6421,7 @@
     return std::nullopt;
 }
 
-std::shared_ptr<Connection> InputDispatcher::ConnectionManager::getConnection(
+std::shared_ptr<Connection> InputDispatcher::getConnectionLocked(
         const sp<IBinder>& inputConnectionToken) const {
     if (inputConnectionToken == nullptr) {
         return nullptr;
@@ -6366,8 +6436,16 @@
     return nullptr;
 }
 
-void InputDispatcher::ConnectionManager::removeConnection(
-        const std::shared_ptr<Connection>& connection) {
+std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const {
+    std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
+    if (connection == nullptr) {
+        return "<nullptr>";
+    }
+    return connection->getInputChannelName();
+}
+
+void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) {
+    mAnrTracker.eraseToken(connection->getToken());
     mConnectionsByToken.erase(connection->getToken());
 }
 
@@ -6595,7 +6673,7 @@
     if (connection.monitor) {
         ALOGW("Monitor %s is unresponsive: %s", connection.getInputChannelName().c_str(),
               reason.c_str());
-        pid = mConnectionManager.findMonitorPidByToken(connectionToken);
+        pid = findMonitorPidByTokenLocked(connectionToken);
     } else {
         // The connection is a window
         ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(),
@@ -6615,7 +6693,7 @@
     const sp<IBinder>& connectionToken = connection.getToken();
     std::optional<gui::Pid> pid;
     if (connection.monitor) {
-        pid = mConnectionManager.findMonitorPidByToken(connectionToken);
+        pid = findMonitorPidByTokenLocked(connectionToken);
     } else {
         // The connection is a window
         const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken);
@@ -7176,10 +7254,10 @@
         state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
                                 deviceId, pointers, downTimeInTarget);
         std::shared_ptr<Connection> wallpaperConnection =
-                mConnectionManager.getConnection(newWallpaper->getToken());
+                getConnectionLocked(newWallpaper->getToken());
         if (wallpaperConnection != nullptr) {
             std::shared_ptr<Connection> toConnection =
-                    mConnectionManager.getConnection(toWindowHandle->getToken());
+                    getConnectionLocked(toWindowHandle->getToken());
             toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
             synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
                                                            wallpaperFlags, traceTracker);
@@ -7243,123 +7321,4 @@
     }
 }
 
-InputDispatcher::ConnectionManager::ConnectionManager(sp<android::Looper> looper)
-      : mLooper(looper) {}
-
-InputDispatcher::ConnectionManager::~ConnectionManager() {
-    while (!mConnectionsByToken.empty()) {
-        std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
-        removeInputChannel(connection);
-    }
-}
-
-void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
-        std::function<void(const std::shared_ptr<Connection>&)> f) const {
-    for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
-        for (const Monitor& monitor : monitors) {
-            f(monitor.connection);
-        }
-    }
-}
-
-void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
-        ui::LogicalDisplayId displayId,
-        std::function<void(const std::shared_ptr<Connection>&)> f) const {
-    auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
-    if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
-
-    for (const Monitor& monitor : monitorsIt->second) {
-        f(monitor.connection);
-    }
-}
-
-void InputDispatcher::ConnectionManager::createGlobalInputMonitor(
-        ui::LogicalDisplayId displayId, std::unique_ptr<InputChannel>&& inputChannel,
-        const android::IdGenerator& idGenerator, gui::Pid pid) {
-    std::shared_ptr<Connection> connection =
-            std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/true, idGenerator);
-    sp<IBinder> token = connection->getToken();
-    auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
-    if (!inserted) {
-        ALOGE("Created a new connection, but the token %p is already known", token.get());
-    }
-    mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
-}
-
-void InputDispatcher::ConnectionManager::createConnection(
-        std::unique_ptr<InputChannel>&& inputChannel, const android::IdGenerator& idGenerator) {
-    std::shared_ptr<Connection> connection =
-            std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/false, idGenerator);
-    sp<IBinder> token = connection->getToken();
-    auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
-    if (!inserted) {
-        ALOGE("Created a new connection, but the token %p is already known", token.get());
-    }
-}
-
-status_t InputDispatcher::ConnectionManager::removeInputChannel(
-        const std::shared_ptr<Connection>& connection) {
-    removeConnection(connection);
-
-    if (connection->monitor) {
-        removeMonitorChannel(connection->getToken());
-    }
-
-    mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
-
-    connection->status = Connection::Status::ZOMBIE;
-    return OK;
-}
-
-std::string InputDispatcher::ConnectionManager::dump(nsecs_t currentTime) const {
-    std::string dump;
-    if (!mGlobalMonitorsByDisplay.empty()) {
-        for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
-            dump += StringPrintf("Global monitors on display %s:\n", displayId.toString().c_str());
-            const size_t numMonitors = monitors.size();
-            for (size_t i = 0; i < numMonitors; i++) {
-                const Monitor& monitor = monitors[i];
-                const std::shared_ptr<Connection>& connection = monitor.connection;
-                dump += StringPrintf(INDENT "%zu: '%s', ", i,
-                                     connection->getInputChannelName().c_str());
-                dump += "\n";
-            }
-        }
-    } else {
-        dump += "Global Monitors: <none>\n";
-    }
-
-    if (!mConnectionsByToken.empty()) {
-        dump += "Connections:\n";
-        for (const auto& [token, connection] : mConnectionsByToken) {
-            dump += StringPrintf(INDENT "%i: channelName='%s', "
-                                        "status=%s, monitor=%s, responsive=%s\n",
-                                 connection->inputPublisher.getChannel().getFd(),
-                                 connection->getInputChannelName().c_str(),
-                                 ftl::enum_string(connection->status).c_str(),
-                                 toString(connection->monitor), toString(connection->responsive));
-
-            if (!connection->outboundQueue.empty()) {
-                dump += StringPrintf(INDENT2 "OutboundQueue: length=%zu\n",
-                                     connection->outboundQueue.size());
-                dump += dumpQueue(connection->outboundQueue, currentTime);
-            }
-
-            if (!connection->waitQueue.empty()) {
-                dump += StringPrintf(INDENT2 "WaitQueue: length=%zu\n",
-                                     connection->waitQueue.size());
-                dump += dumpQueue(connection->waitQueue, currentTime);
-            }
-            std::string inputStateDump = streamableToString(connection->inputState);
-            if (!inputStateDump.empty()) {
-                dump += INDENT2 "InputState: ";
-                dump += inputStateDump + "\n";
-            }
-        }
-    } else {
-        dump += "Connections: <none>\n";
-    }
-    return dump;
-}
-
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index b41a086..bca1c67 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -260,6 +260,13 @@
             const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
             ui::LogicalDisplayId displayId);
 
+    std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
+            REQUIRES(mLock);
+
+    std::string getConnectionNameLocked(const sp<IBinder>& connectionToken) const REQUIRES(mLock);
+
+    void removeConnectionLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
+
     status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
 
     template <typename T>
@@ -267,6 +274,17 @@
         std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
     };
 
+    // All registered connections mapped by input channel token.
+    std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
+            mConnectionsByToken GUARDED_BY(mLock);
+
+    // Find a monitor pid by the provided token.
+    std::optional<gui::Pid> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
+
+    // Input channels that will receive a copy of all input events sent to the provided display.
+    std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay
+            GUARDED_BY(mLock);
+
     const HmacKeyManager mHmacKeyManager;
     const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry,
                                                const DispatchEntry& dispatchEntry) const;
@@ -399,48 +417,6 @@
 
     DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock);
 
-    class ConnectionManager {
-    public:
-        ConnectionManager(sp<Looper> lopper);
-        ~ConnectionManager();
-
-        std::shared_ptr<Connection> getConnection(const sp<IBinder>& inputConnectionToken) const;
-
-        // Find a monitor pid by the provided token.
-        std::optional<gui::Pid> findMonitorPidByToken(const sp<IBinder>& token) const;
-        void forEachGlobalMonitorConnection(
-                std::function<void(const std::shared_ptr<Connection>&)> f) const;
-        void forEachGlobalMonitorConnection(
-                ui::LogicalDisplayId displayId,
-                std::function<void(const std::shared_ptr<Connection>&)> f) const;
-
-        void createGlobalInputMonitor(ui::LogicalDisplayId displayId,
-                                      std::unique_ptr<InputChannel>&& inputChannel,
-                                      const IdGenerator& idGenerator, gui::Pid pid);
-
-        status_t removeInputChannel(const std::shared_ptr<Connection>& connection);
-        void removeConnection(const std::shared_ptr<Connection>& connection);
-
-        void createConnection(std::unique_ptr<InputChannel>&& inputChannel,
-                              const IdGenerator& idGenerator);
-
-        std::string dump(nsecs_t currentTime) const;
-
-    private:
-        sp<Looper> mLooper;
-
-        // All registered connections mapped by input channel token.
-        std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
-                mConnectionsByToken;
-
-        // Input channels that will receive a copy of all input events sent to the provided display.
-        std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay;
-
-        void removeMonitorChannel(const sp<IBinder>& connectionToken);
-    };
-
-    ConnectionManager mConnectionManager GUARDED_BY(mLock);
-
     void setInputWindowsLocked(
             const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
             ui::LogicalDisplayId displayId) REQUIRES(mLock);
@@ -606,6 +582,8 @@
                                   nsecs_t& nextWakeupTime) REQUIRES(mLock);
     base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
     findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock);
+    std::vector<Monitor> selectResponsiveMonitorsLocked(
+            const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock);
 
     void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
                                InputTarget::DispatchMode dispatchMode,
@@ -711,9 +689,12 @@
 
     // Dump state.
     void dumpDispatchStateLocked(std::string& dump) const REQUIRES(mLock);
+    void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const;
     void logDispatchStateLocked() const REQUIRES(mLock);
     std::string dumpPointerCaptureStateLocked() const REQUIRES(mLock);
 
+    // Registration.
+    void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock);
     status_t removeInputChannelLocked(const std::shared_ptr<Connection>& connection, bool notify)
             REQUIRES(mLock);