Loading include/input/InputTransport.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -229,7 +229,7 @@ public: InputChannel(const InputChannel& other) InputChannel(const InputChannel& other) : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){}; : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){}; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); virtual ~InputChannel(); ~InputChannel() override; /** /** * Create a pair of input channels. * Create a pair of input channels. * The two returned input channels are equivalent, and are labeled as "server" and "client" * The two returned input channels are equivalent, and are labeled as "server" and "client" Loading services/inputflinger/dispatcher/InputDispatcher.cpp +104 −116 Original line number Original line Diff line number Diff line Loading @@ -283,27 +283,6 @@ static V getValueByKey(const std::unordered_map<K, V>& map, K key) { return it != map.end() ? it->second : V{}; return it != map.end() ? it->second : V{}; } } /** * Find the entry in std::unordered_map by value, and remove it. * If more than one entry has the same value, then all matching * key-value pairs will be removed. * * Return true if at least one value has been removed. */ template <typename K, typename V> static bool removeByValue(std::unordered_map<K, V>& map, const V& value) { bool removed = false; for (auto it = map.begin(); it != map.end();) { if (it->second == value) { it = map.erase(it); removed = true; } else { it++; } } return removed; } static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) { static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) { if (first == second) { if (first == second) { return true; return true; Loading Loading @@ -507,8 +486,8 @@ InputDispatcher::~InputDispatcher() { drainInboundQueueLocked(); drainInboundQueueLocked(); } } while (!mConnectionsByFd.empty()) { while (!mConnectionsByToken.empty()) { sp<Connection> connection = mConnectionsByFd.begin()->second; sp<Connection> connection = mConnectionsByToken.begin()->second; removeInputChannel(connection->inputChannel->getConnectionToken()); removeInputChannel(connection->inputChannel->getConnectionToken()); } } } } Loading Loading @@ -3297,21 +3276,16 @@ void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) { delete dispatchEntry; delete dispatchEntry; } } int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) { InputDispatcher* d = static_cast<InputDispatcher*>(data); std::scoped_lock _l(mLock); sp<Connection> connection = getConnectionLocked(connectionToken); { // acquire lock if (connection == nullptr) { std::scoped_lock _l(d->mLock); ALOGW("Received looper callback for unknown input channel token %p. events=0x%x", connectionToken.get(), events); if (d->mConnectionsByFd.find(fd) == d->mConnectionsByFd.end()) { ALOGE("Received spurious receive callback for unknown input channel. " "fd=%d, events=0x%x", fd, events); return 0; // remove the callback return 0; // remove the callback } } bool notify; bool notify; sp<Connection> connection = d->mConnectionsByFd[fd]; if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { if (!(events & ALOOPER_EVENT_INPUT)) { if (!(events & ALOOPER_EVENT_INPUT)) { ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " Loading @@ -3334,15 +3308,15 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { if (std::holds_alternative<InputPublisher::Finished>(*result)) { if (std::holds_alternative<InputPublisher::Finished>(*result)) { const InputPublisher::Finished& finish = const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*result); std::get<InputPublisher::Finished>(*result); d->finishDispatchCycleLocked(currentTime, connection, finish.seq, finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled, finish.handled, finish.consumeTime); finish.consumeTime); } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) { } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) { // TODO(b/167947340): Report this data to LatencyTracker // TODO(b/167947340): Report this data to LatencyTracker } } gotOne = true; gotOne = true; } } if (gotOne) { if (gotOne) { d->runCommandsLockedInterruptible(); runCommandsLockedInterruptible(); if (status == WOULD_BLOCK) { if (status == WOULD_BLOCK) { return 1; return 1; } } Loading @@ -3358,25 +3332,22 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { // Monitor channels are never explicitly unregistered. // Monitor channels are never explicitly unregistered. // We do it automatically when the remote endpoint is closed so don't warn about them. // We do it automatically when the remote endpoint is closed so don't warn about them. const bool stillHaveWindowHandle = const bool stillHaveWindowHandle = d->getWindowHandleLocked(connection->inputChannel->getConnectionToken()) != getWindowHandleLocked(connection->inputChannel->getConnectionToken()) != nullptr; nullptr; notify = !connection->monitor && stillHaveWindowHandle; notify = !connection->monitor && stillHaveWindowHandle; if (notify) { if (notify) { ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. " ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. events=0x%x", "events=0x%x", connection->getInputChannelName().c_str(), events); connection->getInputChannelName().c_str(), events); } } } } // Remove the channel. // Remove the channel. d->removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify); removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify); return 0; // remove the callback return 0; // remove the callback } // release lock } } void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( const CancelationOptions& options) { const CancelationOptions& options) { for (const auto& [fd, connection] : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { synthesizeCancelationEventsForConnectionLocked(connection, options); synthesizeCancelationEventsForConnectionLocked(connection, options); } } } } Loading Loading @@ -4342,11 +4313,11 @@ bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHan std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked( std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked( const sp<IBinder>& token) const { const sp<IBinder>& token) const { size_t count = mInputChannelsByToken.count(token); auto connectionIt = mConnectionsByToken.find(token); if (count == 0) { if (connectionIt == mConnectionsByToken.end()) { return nullptr; return nullptr; } } return mInputChannelsByToken.at(token); return connectionIt->second->inputChannel; } } void InputDispatcher::updateWindowHandlesForDisplayLocked( void InputDispatcher::updateWindowHandlesForDisplayLocked( Loading Loading @@ -4996,13 +4967,13 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "ReplacedKeys: <empty>\n"; dump += INDENT "ReplacedKeys: <empty>\n"; } } if (!mConnectionsByFd.empty()) { if (!mConnectionsByToken.empty()) { dump += INDENT "Connections:\n"; dump += INDENT "Connections:\n"; for (const auto& pair : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { const sp<Connection>& connection = pair.second; dump += StringPrintf(INDENT2 "%i: channelName='%s', windowName='%s', " dump += StringPrintf(INDENT2 "%i: channelName='%s', windowName='%s', " "status=%s, monitor=%s, responsive=%s\n", "status=%s, monitor=%s, responsive=%s\n", pair.first, connection->getInputChannelName().c_str(), connection->inputChannel->getFd().get(), connection->getInputChannelName().c_str(), connection->getWindowName().c_str(), connection->getStatusLabel(), connection->getWindowName().c_str(), connection->getStatusLabel(), toString(connection->monitor), toString(connection->responsive)); toString(connection->monitor), toString(connection->responsive)); Loading Loading @@ -5050,14 +5021,23 @@ void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor> } } } } class LooperEventCallback : public LooperCallback { public: LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {} int handleEvent(int /*fd*/, int events, void* /*data*/) override { return mCallback(events); } private: std::function<int(int events)> mCallback; }; Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) { Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) { #if DEBUG_CHANNEL_CREATION #if DEBUG_CHANNEL_CREATION ALOGD("channel '%s' ~ createInputChannel", name.c_str()); ALOGD("channel '%s' ~ createInputChannel", name.c_str()); #endif #endif std::shared_ptr<InputChannel> serverChannel; std::unique_ptr<InputChannel> serverChannel; std::unique_ptr<InputChannel> clientChannel; std::unique_ptr<InputChannel> clientChannel; status_t result = openInputChannelPair(name, serverChannel, clientChannel); status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel); if (result) { if (result) { return base::Error(result) << "Failed to open input channel pair with name " << name; return base::Error(result) << "Failed to open input channel pair with name " << name; Loading @@ -5065,13 +5045,20 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const { // acquire lock { // acquire lock std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); sp<Connection> connection = new Connection(serverChannel, false /*monitor*/, mIdGenerator); const sp<IBinder>& token = serverChannel->getConnectionToken(); int fd = serverChannel->getFd(); int fd = serverChannel->getFd(); mConnectionsByFd[fd] = connection; sp<Connection> connection = mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel; new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator); if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) { ALOGE("Created a new connection, but the token %p is already known", token.get()); } mConnectionsByToken.emplace(token, connection); std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); } // release lock } // release lock // Wake the looper because some connections have changed. // Wake the looper because some connections have changed. Loading Loading @@ -5099,18 +5086,21 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_ } } sp<Connection> connection = new Connection(serverChannel, true /*monitor*/, mIdGenerator); sp<Connection> connection = new Connection(serverChannel, true /*monitor*/, mIdGenerator); const sp<IBinder>& token = serverChannel->getConnectionToken(); const int fd = serverChannel->getFd(); const int fd = serverChannel->getFd(); mConnectionsByFd[fd] = connection; mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel; if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) { ALOGE("Created a new connection, but the token %p is already known", token.get()); } mConnectionsByToken.emplace(token, connection); std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); auto& monitorsByDisplay = auto& monitorsByDisplay = isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; monitorsByDisplay[displayId].emplace_back(serverChannel, pid); monitorsByDisplay[displayId].emplace_back(serverChannel, pid); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); ALOGI("Created monitor %s for display %" PRId32 ", gesture=%s, pid=%" PRId32, name.c_str(), displayId, toString(isGestureMonitor), pid); } } // Wake the looper because some connections have changed. // Wake the looper because some connections have changed. Loading Loading @@ -5143,7 +5133,6 @@ status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connection } } removeConnectionLocked(connection); removeConnectionLocked(connection); mInputChannelsByToken.erase(connectionToken); if (connection->monitor) { if (connection->monitor) { removeMonitorChannelLocked(connectionToken); removeMonitorChannelLocked(connectionToken); Loading Loading @@ -5301,9 +5290,8 @@ sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConn return nullptr; return nullptr; } } for (const auto& pair : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { const sp<Connection>& connection = pair.second; if (token == inputConnectionToken) { if (connection->inputChannel->getConnectionToken() == inputConnectionToken) { return connection; return connection; } } } } Loading @@ -5321,7 +5309,7 @@ std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connecti void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) { void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) { mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); removeByValue(mConnectionsByFd, connection); mConnectionsByToken.erase(connection->inputChannel->getConnectionToken()); } } void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime, void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime, Loading services/inputflinger/dispatcher/InputDispatcher.h +5 −6 Original line number Original line Diff line number Diff line Loading @@ -211,9 +211,6 @@ private: bool addPortalWindows = false, bool addPortalWindows = false, bool ignoreDragWindow = false) REQUIRES(mLock); bool ignoreDragWindow = false) REQUIRES(mLock); // All registered connections mapped by channel file descriptor. std::unordered_map<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock); sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const REQUIRES(mLock); REQUIRES(mLock); Loading @@ -225,8 +222,10 @@ private: struct StrongPointerHash { struct StrongPointerHash { std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } }; }; std::unordered_map<sp<IBinder>, std::shared_ptr<InputChannel>, StrongPointerHash<IBinder>> mInputChannelsByToken GUARDED_BY(mLock); // All registered connections mapped by input channel token. std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) Loading Loading @@ -544,7 +543,7 @@ private: bool notify) REQUIRES(mLock); bool notify) REQUIRES(mLock); void drainDispatchQueue(std::deque<DispatchEntry*>& queue); void drainDispatchQueue(std::deque<DispatchEntry*>& queue); void releaseDispatchEntry(DispatchEntry* dispatchEntry); void releaseDispatchEntry(DispatchEntry* dispatchEntry); static int handleReceiveCallback(int fd, int events, void* data); int handleReceiveCallback(int events, sp<IBinder> connectionToken); // The action sent should only be of type AMOTION_EVENT_* // The action sent should only be of type AMOTION_EVENT_* void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, const sp<IBinder>& newToken) REQUIRES(mLock); const sp<IBinder>& newToken) REQUIRES(mLock); Loading Loading
include/input/InputTransport.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -229,7 +229,7 @@ public: InputChannel(const InputChannel& other) InputChannel(const InputChannel& other) : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){}; : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){}; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); virtual ~InputChannel(); ~InputChannel() override; /** /** * Create a pair of input channels. * Create a pair of input channels. * The two returned input channels are equivalent, and are labeled as "server" and "client" * The two returned input channels are equivalent, and are labeled as "server" and "client" Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +104 −116 Original line number Original line Diff line number Diff line Loading @@ -283,27 +283,6 @@ static V getValueByKey(const std::unordered_map<K, V>& map, K key) { return it != map.end() ? it->second : V{}; return it != map.end() ? it->second : V{}; } } /** * Find the entry in std::unordered_map by value, and remove it. * If more than one entry has the same value, then all matching * key-value pairs will be removed. * * Return true if at least one value has been removed. */ template <typename K, typename V> static bool removeByValue(std::unordered_map<K, V>& map, const V& value) { bool removed = false; for (auto it = map.begin(); it != map.end();) { if (it->second == value) { it = map.erase(it); removed = true; } else { it++; } } return removed; } static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) { static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) { if (first == second) { if (first == second) { return true; return true; Loading Loading @@ -507,8 +486,8 @@ InputDispatcher::~InputDispatcher() { drainInboundQueueLocked(); drainInboundQueueLocked(); } } while (!mConnectionsByFd.empty()) { while (!mConnectionsByToken.empty()) { sp<Connection> connection = mConnectionsByFd.begin()->second; sp<Connection> connection = mConnectionsByToken.begin()->second; removeInputChannel(connection->inputChannel->getConnectionToken()); removeInputChannel(connection->inputChannel->getConnectionToken()); } } } } Loading Loading @@ -3297,21 +3276,16 @@ void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) { delete dispatchEntry; delete dispatchEntry; } } int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) { InputDispatcher* d = static_cast<InputDispatcher*>(data); std::scoped_lock _l(mLock); sp<Connection> connection = getConnectionLocked(connectionToken); { // acquire lock if (connection == nullptr) { std::scoped_lock _l(d->mLock); ALOGW("Received looper callback for unknown input channel token %p. events=0x%x", connectionToken.get(), events); if (d->mConnectionsByFd.find(fd) == d->mConnectionsByFd.end()) { ALOGE("Received spurious receive callback for unknown input channel. " "fd=%d, events=0x%x", fd, events); return 0; // remove the callback return 0; // remove the callback } } bool notify; bool notify; sp<Connection> connection = d->mConnectionsByFd[fd]; if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) { if (!(events & ALOOPER_EVENT_INPUT)) { if (!(events & ALOOPER_EVENT_INPUT)) { ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " Loading @@ -3334,15 +3308,15 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { if (std::holds_alternative<InputPublisher::Finished>(*result)) { if (std::holds_alternative<InputPublisher::Finished>(*result)) { const InputPublisher::Finished& finish = const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*result); std::get<InputPublisher::Finished>(*result); d->finishDispatchCycleLocked(currentTime, connection, finish.seq, finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled, finish.handled, finish.consumeTime); finish.consumeTime); } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) { } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) { // TODO(b/167947340): Report this data to LatencyTracker // TODO(b/167947340): Report this data to LatencyTracker } } gotOne = true; gotOne = true; } } if (gotOne) { if (gotOne) { d->runCommandsLockedInterruptible(); runCommandsLockedInterruptible(); if (status == WOULD_BLOCK) { if (status == WOULD_BLOCK) { return 1; return 1; } } Loading @@ -3358,25 +3332,22 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { // Monitor channels are never explicitly unregistered. // Monitor channels are never explicitly unregistered. // We do it automatically when the remote endpoint is closed so don't warn about them. // We do it automatically when the remote endpoint is closed so don't warn about them. const bool stillHaveWindowHandle = const bool stillHaveWindowHandle = d->getWindowHandleLocked(connection->inputChannel->getConnectionToken()) != getWindowHandleLocked(connection->inputChannel->getConnectionToken()) != nullptr; nullptr; notify = !connection->monitor && stillHaveWindowHandle; notify = !connection->monitor && stillHaveWindowHandle; if (notify) { if (notify) { ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. " ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. events=0x%x", "events=0x%x", connection->getInputChannelName().c_str(), events); connection->getInputChannelName().c_str(), events); } } } } // Remove the channel. // Remove the channel. d->removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify); removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify); return 0; // remove the callback return 0; // remove the callback } // release lock } } void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( const CancelationOptions& options) { const CancelationOptions& options) { for (const auto& [fd, connection] : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { synthesizeCancelationEventsForConnectionLocked(connection, options); synthesizeCancelationEventsForConnectionLocked(connection, options); } } } } Loading Loading @@ -4342,11 +4313,11 @@ bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHan std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked( std::shared_ptr<InputChannel> InputDispatcher::getInputChannelLocked( const sp<IBinder>& token) const { const sp<IBinder>& token) const { size_t count = mInputChannelsByToken.count(token); auto connectionIt = mConnectionsByToken.find(token); if (count == 0) { if (connectionIt == mConnectionsByToken.end()) { return nullptr; return nullptr; } } return mInputChannelsByToken.at(token); return connectionIt->second->inputChannel; } } void InputDispatcher::updateWindowHandlesForDisplayLocked( void InputDispatcher::updateWindowHandlesForDisplayLocked( Loading Loading @@ -4996,13 +4967,13 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) { dump += INDENT "ReplacedKeys: <empty>\n"; dump += INDENT "ReplacedKeys: <empty>\n"; } } if (!mConnectionsByFd.empty()) { if (!mConnectionsByToken.empty()) { dump += INDENT "Connections:\n"; dump += INDENT "Connections:\n"; for (const auto& pair : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { const sp<Connection>& connection = pair.second; dump += StringPrintf(INDENT2 "%i: channelName='%s', windowName='%s', " dump += StringPrintf(INDENT2 "%i: channelName='%s', windowName='%s', " "status=%s, monitor=%s, responsive=%s\n", "status=%s, monitor=%s, responsive=%s\n", pair.first, connection->getInputChannelName().c_str(), connection->inputChannel->getFd().get(), connection->getInputChannelName().c_str(), connection->getWindowName().c_str(), connection->getStatusLabel(), connection->getWindowName().c_str(), connection->getStatusLabel(), toString(connection->monitor), toString(connection->responsive)); toString(connection->monitor), toString(connection->responsive)); Loading Loading @@ -5050,14 +5021,23 @@ void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor> } } } } class LooperEventCallback : public LooperCallback { public: LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {} int handleEvent(int /*fd*/, int events, void* /*data*/) override { return mCallback(events); } private: std::function<int(int events)> mCallback; }; Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) { Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) { #if DEBUG_CHANNEL_CREATION #if DEBUG_CHANNEL_CREATION ALOGD("channel '%s' ~ createInputChannel", name.c_str()); ALOGD("channel '%s' ~ createInputChannel", name.c_str()); #endif #endif std::shared_ptr<InputChannel> serverChannel; std::unique_ptr<InputChannel> serverChannel; std::unique_ptr<InputChannel> clientChannel; std::unique_ptr<InputChannel> clientChannel; status_t result = openInputChannelPair(name, serverChannel, clientChannel); status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel); if (result) { if (result) { return base::Error(result) << "Failed to open input channel pair with name " << name; return base::Error(result) << "Failed to open input channel pair with name " << name; Loading @@ -5065,13 +5045,20 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const { // acquire lock { // acquire lock std::scoped_lock _l(mLock); std::scoped_lock _l(mLock); sp<Connection> connection = new Connection(serverChannel, false /*monitor*/, mIdGenerator); const sp<IBinder>& token = serverChannel->getConnectionToken(); int fd = serverChannel->getFd(); int fd = serverChannel->getFd(); mConnectionsByFd[fd] = connection; sp<Connection> connection = mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel; new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator); if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) { ALOGE("Created a new connection, but the token %p is already known", token.get()); } mConnectionsByToken.emplace(token, connection); std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); } // release lock } // release lock // Wake the looper because some connections have changed. // Wake the looper because some connections have changed. Loading Loading @@ -5099,18 +5086,21 @@ Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_ } } sp<Connection> connection = new Connection(serverChannel, true /*monitor*/, mIdGenerator); sp<Connection> connection = new Connection(serverChannel, true /*monitor*/, mIdGenerator); const sp<IBinder>& token = serverChannel->getConnectionToken(); const int fd = serverChannel->getFd(); const int fd = serverChannel->getFd(); mConnectionsByFd[fd] = connection; mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel; if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) { ALOGE("Created a new connection, but the token %p is already known", token.get()); } mConnectionsByToken.emplace(token, connection); std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback, this, std::placeholders::_1, token); auto& monitorsByDisplay = auto& monitorsByDisplay = isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay; monitorsByDisplay[displayId].emplace_back(serverChannel, pid); monitorsByDisplay[displayId].emplace_back(serverChannel, pid); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr); ALOGI("Created monitor %s for display %" PRId32 ", gesture=%s, pid=%" PRId32, name.c_str(), displayId, toString(isGestureMonitor), pid); } } // Wake the looper because some connections have changed. // Wake the looper because some connections have changed. Loading Loading @@ -5143,7 +5133,6 @@ status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connection } } removeConnectionLocked(connection); removeConnectionLocked(connection); mInputChannelsByToken.erase(connectionToken); if (connection->monitor) { if (connection->monitor) { removeMonitorChannelLocked(connectionToken); removeMonitorChannelLocked(connectionToken); Loading Loading @@ -5301,9 +5290,8 @@ sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConn return nullptr; return nullptr; } } for (const auto& pair : mConnectionsByFd) { for (const auto& [token, connection] : mConnectionsByToken) { const sp<Connection>& connection = pair.second; if (token == inputConnectionToken) { if (connection->inputChannel->getConnectionToken() == inputConnectionToken) { return connection; return connection; } } } } Loading @@ -5321,7 +5309,7 @@ std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connecti void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) { void InputDispatcher::removeConnectionLocked(const sp<Connection>& connection) { mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); removeByValue(mConnectionsByFd, connection); mConnectionsByToken.erase(connection->inputChannel->getConnectionToken()); } } void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime, void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime, Loading
services/inputflinger/dispatcher/InputDispatcher.h +5 −6 Original line number Original line Diff line number Diff line Loading @@ -211,9 +211,6 @@ private: bool addPortalWindows = false, bool addPortalWindows = false, bool ignoreDragWindow = false) REQUIRES(mLock); bool ignoreDragWindow = false) REQUIRES(mLock); // All registered connections mapped by channel file descriptor. std::unordered_map<int, sp<Connection>> mConnectionsByFd GUARDED_BY(mLock); sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const sp<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const REQUIRES(mLock); REQUIRES(mLock); Loading @@ -225,8 +222,10 @@ private: struct StrongPointerHash { struct StrongPointerHash { std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); } }; }; std::unordered_map<sp<IBinder>, std::shared_ptr<InputChannel>, StrongPointerHash<IBinder>> mInputChannelsByToken GUARDED_BY(mLock); // All registered connections mapped by input channel token. std::unordered_map<sp<IBinder>, sp<Connection>, StrongPointerHash<IBinder>> mConnectionsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) Loading Loading @@ -544,7 +543,7 @@ private: bool notify) REQUIRES(mLock); bool notify) REQUIRES(mLock); void drainDispatchQueue(std::deque<DispatchEntry*>& queue); void drainDispatchQueue(std::deque<DispatchEntry*>& queue); void releaseDispatchEntry(DispatchEntry* dispatchEntry); void releaseDispatchEntry(DispatchEntry* dispatchEntry); static int handleReceiveCallback(int fd, int events, void* data); int handleReceiveCallback(int events, sp<IBinder> connectionToken); // The action sent should only be of type AMOTION_EVENT_* // The action sent should only be of type AMOTION_EVENT_* void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, const sp<IBinder>& newToken) REQUIRES(mLock); const sp<IBinder>& newToken) REQUIRES(mLock); Loading