diff options
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 271 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 56 |
2 files changed, 197 insertions, 130 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 15df89b990..b5287a2254 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1128,7 +1128,7 @@ std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked( if (connection->monitor) { return mMonitorDispatchingTimeout; } - const sp<WindowInfoHandle> window = getWindowHandleLocked(connection->getToken()); + const sp<WindowInfoHandle> window = mWindowInfos.findWindowHandle(connection->getToken()); if (window != nullptr) { return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT); } @@ -1456,7 +1456,7 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(ui::LogicalDispl float x, float y, bool isStylus, bool ignoreDragWindow) const { // Traverse windows from front to back to find touched window. - const auto& windowHandles = getWindowHandlesLocked(displayId); + const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) { continue; @@ -1464,7 +1464,8 @@ sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(ui::LogicalDispl const WindowInfo& info = *windowHandle->getInfo(); if (!info.isSpy() && - windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) { + windowAcceptsTouchAt(info, displayId, x, y, isStylus, + mWindowInfos.getDisplayTransform(displayId))) { return windowHandle; } } @@ -1479,7 +1480,7 @@ std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked( } // Traverse windows from front to back until we encounter the touched window. std::vector<InputTarget> outsideTargets; - const auto& windowHandles = getWindowHandlesLocked(displayId); + const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { if (windowHandle == touchedWindow) { // Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window @@ -1503,10 +1504,11 @@ std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked ui::LogicalDisplayId displayId, float x, float y, bool isStylus, DeviceId deviceId) const { // Traverse windows from front to back and gather the touched spy windows. std::vector<sp<WindowInfoHandle>> spyWindows; - const auto& windowHandles = getWindowHandlesLocked(displayId); + const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId); for (const sp<WindowInfoHandle>& windowHandle : windowHandles) { const WindowInfo& info = *windowHandle->getInfo(); - if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) { + if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, + mWindowInfos.getDisplayTransform(displayId))) { // Generally, we would skip any pointer that's outside of the window. However, if the // spy prevents splitting, and already has some of the pointers from this device, then // it should get more pointers from the same device, even if they are outside of that @@ -1828,7 +1830,7 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked( void InputDispatcher::dispatchTouchModeChangeLocked( nsecs_t currentTime, const std::shared_ptr<const TouchModeEntry>& entry) { const std::vector<sp<WindowInfoHandle>>& windowHandles = - getWindowHandlesLocked(entry->displayId); + mWindowInfos.getWindowHandlesForDisplay(entry->displayId); if (windowHandles.empty()) { return; } @@ -2216,7 +2218,7 @@ void InputDispatcher::cancelEventsForAnrLocked(const std::shared_ptr<Connection> sp<WindowInfoHandle> windowHandle; if (!connection->monitor) { - windowHandle = getWindowHandleLocked(connection->getToken()); + windowHandle = mWindowInfos.findWindowHandle(connection->getToken()); if (windowHandle == nullptr) { // The window that is receiving this ANR was removed, so there is no need to generate // cancellations, because the cancellations would have already been generated when @@ -2779,7 +2781,7 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio for (InputTarget& target : targets) { if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) { sp<WindowInfoHandle> targetWindow = - getWindowHandleLocked(target.connection->getToken()); + mWindowInfos.findWindowHandle(target.connection->getToken()); if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) { target.flags |= InputTarget::Flags::ZERO_COORDS; } @@ -2985,13 +2987,8 @@ std::optional<InputTarget> InputDispatcher::createInputTargetLocked( inputTarget.flags = targetFlags; inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor; inputTarget.firstDownTimeInTarget = firstDownTimeInTarget; - const auto& displayInfoIt = mDisplayInfos.find(windowHandle->getInfo()->displayId); - if (displayInfoIt != mDisplayInfos.end()) { - inputTarget.displayTransform = displayInfoIt->second.transform; - } else { - // DisplayInfo not found for this window on display windowHandle->getInfo()->displayId. - // TODO(b/198444055): Make this an error message after 'setInputWindows' API is removed. - } + inputTarget.displayTransform = + mWindowInfos.getDisplayTransform(windowHandle->getInfo()->displayId); return inputTarget; } @@ -3099,9 +3096,7 @@ void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& 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 - if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { - target.displayTransform = it->second.transform; - } + target.displayTransform = mWindowInfos.getDisplayTransform(displayId); target.setDefaultPointerTransform(target.displayTransform); inputTargets.push_back(target); } @@ -3164,7 +3159,8 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo const sp<WindowInfoHandle>& windowHandle, float x, float y) const { const WindowInfo* windowInfo = windowHandle->getInfo(); ui::LogicalDisplayId displayId = windowInfo->displayId; - const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>>& windowHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); TouchOcclusionInfo info; info.hasBlockingOcclusion = false; info.obscuringOpacity = 0; @@ -3176,7 +3172,8 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && - windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) && + windowOccludesTouchAt(*otherInfo, displayId, x, y, + mWindowInfos.getDisplayTransform(displayId)) && !haveSameApplicationToken(windowInfo, otherInfo)) { if (DEBUG_TOUCH_OCCLUSION) { info.debugInfo.push_back( @@ -3248,14 +3245,16 @@ bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionIn bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle, float x, float y) const { ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId; - const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>>& windowHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); for (const sp<WindowInfoHandle>& otherHandle : windowHandles) { if (windowHandle == otherHandle) { break; // All future windows are below us. Exit early. } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && - windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) { + windowOccludesTouchAt(*otherInfo, displayId, x, y, + mWindowInfos.getDisplayTransform(displayId))) { return true; } } @@ -3264,7 +3263,8 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& bool InputDispatcher::isWindowObscuredLocked(const sp<WindowInfoHandle>& windowHandle) const { ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId; - const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>>& windowHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); const WindowInfo* windowInfo = windowHandle->getInfo(); for (const sp<WindowInfoHandle>& otherHandle : windowHandles) { if (windowHandle == otherHandle) { @@ -4118,7 +4118,8 @@ int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionTok } else { // Monitor channels are never explicitly unregistered. // We do it automatically when the remote endpoint is closed so don't warn about them. - const bool stillHaveWindowHandle = getWindowHandleLocked(connection->getToken()) != nullptr; + const bool stillHaveWindowHandle = + mWindowInfos.findWindowHandle(connection->getToken()) != nullptr; notify = !connection->monitor && stillHaveWindowHandle; if (notify) { ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. events=0x%x", @@ -4153,11 +4154,11 @@ void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked( // Follow up by generating cancellations for all windows, because we don't explicitly track // the windows that have an ongoing focus event stream. if (cancelNonPointers) { - for (const auto& [_, handles] : mWindowHandlesByDisplay) { - for (const auto& windowHandle : handles) { - synthesizeCancelationEventsForWindowLocked(windowHandle, options); - } - } + mWindowInfos.forEachWindowHandle( + [&](const sp<android::gui::WindowInfoHandle>& windowHandle) { + base::ScopedLockAssertion assumeLocked(mLock); + synthesizeCancelationEventsForWindowLocked(windowHandle, options); + }); } // Cancel monitors. @@ -4281,11 +4282,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( motionEntry.downTime, targets); } else { targets.emplace_back(fallbackTarget); - const auto it = mDisplayInfos.find(motionEntry.displayId); - if (it != mDisplayInfos.end()) { - targets.back().displayTransform = it->second.transform; - targets.back().setDefaultPointerTransform(it->second.transform); - } + const ui::Transform displayTransform = + mWindowInfos.getDisplayTransform(motionEntry.displayId); + targets.back().displayTransform = displayTransform; + targets.back().setDefaultPointerTransform(displayTransform); } logOutboundMotionDetails("cancel - ", motionEntry); break; @@ -4367,11 +4367,10 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( targets); } else { targets.emplace_back(connection, targetFlags); - const auto it = mDisplayInfos.find(motionEntry.displayId); - if (it != mDisplayInfos.end()) { - targets.back().displayTransform = it->second.transform; - targets.back().setDefaultPointerTransform(it->second.transform); - } + const ui::Transform displayTransform = + mWindowInfos.getDisplayTransform(motionEntry.displayId); + targets.back().displayTransform = displayTransform; + targets.back().setDefaultPointerTransform(displayTransform); } logOutboundMotionDetails("down - ", motionEntry); break; @@ -4642,10 +4641,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) { } if (shouldSendMotionToInputFilterLocked(args)) { - ui::Transform displayTransform; - if (const auto it = mDisplayInfos.find(args.displayId); it != mDisplayInfos.end()) { - displayTransform = it->second.transform; - } + ui::Transform displayTransform = mWindowInfos.getDisplayTransform(args.displayId); mLock.unlock(); @@ -5149,9 +5145,8 @@ void InputDispatcher::transformMotionEntryForInjectionLocked( MotionEntry& entry, const ui::Transform& injectedTransform) const { // Input injection works in the logical display coordinate space, but the input pipeline works // display space, so we need to transform the injected events accordingly. - const auto it = mDisplayInfos.find(entry.displayId); - if (it == mDisplayInfos.end()) return; - const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform; + const ui::Transform displayTransform = mWindowInfos.getDisplayTransform(entry.displayId); + const auto& transformToDisplay = displayTransform.inverse() * injectedTransform; if (entry.xCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && entry.yCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { @@ -5184,14 +5179,7 @@ void InputDispatcher::decrementPendingForegroundDispatches(const EventEntry& ent } } -const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked( - ui::LogicalDisplayId displayId) const { - static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES; - auto it = mWindowHandlesByDisplay.find(displayId); - return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES; -} - -sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked( +sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWindowHandle( const sp<IBinder>& windowHandleToken, std::optional<ui::LogicalDisplayId> displayId) const { if (windowHandleToken == nullptr) { return nullptr; @@ -5210,7 +5198,7 @@ sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked( } // Only look through the requested display. - for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(*displayId)) { + for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesForDisplay(*displayId)) { if (windowHandle->getToken() == windowHandleToken) { return windowHandle; } @@ -5218,7 +5206,8 @@ sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked( return nullptr; } -bool InputDispatcher::isWindowPresentLocked(const sp<WindowInfoHandle>& windowHandle) const { +bool InputDispatcher::DispatcherWindowInfo::isWindowPresent( + const sp<WindowInfoHandle>& windowHandle) const { for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) { for (const sp<WindowInfoHandle>& handle : windowHandles) { if (handle->getId() == windowHandle->getId() && @@ -5239,15 +5228,88 @@ bool InputDispatcher::isWindowPresentLocked(const sp<WindowInfoHandle>& windowHa sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked( ui::LogicalDisplayId displayId) const { sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId); - return getWindowHandleLocked(focusedToken, displayId); + return mWindowInfos.findWindowHandle(focusedToken, displayId); +} + +void InputDispatcher::DispatcherWindowInfo::setWindowHandlesForDisplay( + ui::LogicalDisplayId displayId, std::vector<sp<WindowInfoHandle>>&& windowHandles) { + // Insert or replace + mWindowHandlesByDisplay[displayId] = std::move(windowHandles); } -ui::Transform InputDispatcher::getTransformLocked(ui::LogicalDisplayId displayId) const { +void InputDispatcher::DispatcherWindowInfo::setDisplayInfos( + const std::vector<android::gui::DisplayInfo>& displayInfos) { + mDisplayInfos.clear(); + for (const auto& displayInfo : displayInfos) { + mDisplayInfos.emplace(displayInfo.displayId, displayInfo); + } +} + +void InputDispatcher::DispatcherWindowInfo::removeDisplay(ui::LogicalDisplayId displayId) { + mWindowHandlesByDisplay.erase(displayId); +} + +const std::vector<sp<android::gui::WindowInfoHandle>>& +InputDispatcher::DispatcherWindowInfo::getWindowHandlesForDisplay( + ui::LogicalDisplayId displayId) const { + static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES; + const auto it = mWindowHandlesByDisplay.find(displayId); + return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES; +} + +void InputDispatcher::DispatcherWindowInfo::forEachWindowHandle( + std::function<void(const sp<android::gui::WindowInfoHandle>&)> f) const { + for (const auto& [_, windowHandles] : mWindowHandlesByDisplay) { + for (const auto& windowHandle : windowHandles) { + f(windowHandle); + } + } +} + +void InputDispatcher::DispatcherWindowInfo::forEachDisplayId( + std::function<void(ui::LogicalDisplayId)> f) const { + for (const auto& [displayId, _] : mWindowHandlesByDisplay) { + f(displayId); + } +} + +ui::Transform InputDispatcher::DispatcherWindowInfo::getDisplayTransform( + ui::LogicalDisplayId displayId) const { auto displayInfoIt = mDisplayInfos.find(displayId); return displayInfoIt != mDisplayInfos.end() ? displayInfoIt->second.transform : kIdentityTransform; } +std::string InputDispatcher::DispatcherWindowInfo::dumpDisplayAndWindowInfo() const { + std::string dump; + if (!mWindowHandlesByDisplay.empty()) { + for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) { + dump += StringPrintf("Display: %s\n", displayId.toString().c_str()); + if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { + const auto& displayInfo = it->second; + dump += StringPrintf(INDENT "logicalSize=%dx%d\n", displayInfo.logicalWidth, + displayInfo.logicalHeight); + displayInfo.transform.dump(dump, "transform", INDENT3); + } else { + dump += INDENT "No DisplayInfo found!\n"; + } + + if (!windowHandles.empty()) { + dump += INDENT "Windows:\n"; + for (size_t i = 0; i < windowHandles.size(); i++) { + dump += StringPrintf(INDENT2 "%zu: %s", i, + streamableToString(*windowHandles[i]).c_str()); + } + } else { + dump += INDENT "Windows: <none>\n"; + } + } + } else { + dump += "Displays: <none>\n"; + } + return dump; +} + bool InputDispatcher::canWindowReceiveMotionLocked(const sp<WindowInfoHandle>& window, const MotionEntry& motionEntry) const { const WindowInfo& info = *window->getInfo(); @@ -5315,13 +5377,14 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( ui::LogicalDisplayId displayId) { if (windowInfoHandles.empty()) { // Remove all handles on a display if there are no windows left. - mWindowHandlesByDisplay.erase(displayId); + mWindowInfos.removeDisplay(displayId); return; } // Since we compare the pointer of input window handles across window updates, we need // to make sure the handle object for the same window stays unchanged across updates. - const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>>& oldHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById; for (const sp<WindowInfoHandle>& handle : oldHandles) { oldHandlesById[handle->getId()] = handle; @@ -5360,8 +5423,7 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( } } - // Insert or replace - mWindowHandlesByDisplay[displayId] = newHandles; + mWindowInfos.setWindowHandlesForDisplay(displayId, std::move(newHandles)); } /** @@ -5411,12 +5473,14 @@ void InputDispatcher::setInputWindowsLocked( } // Copy old handles for release if they are no longer present. - const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>> oldWindowHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId); updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); - const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); + const std::vector<sp<WindowInfoHandle>>& windowHandles = + mWindowInfos.getWindowHandlesForDisplay(displayId); std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setInputWindows(displayId, windowHandles); @@ -5428,7 +5492,7 @@ void InputDispatcher::setInputWindowsLocked( TouchState& state = it->second; for (size_t i = 0; i < state.windows.size();) { TouchedWindow& touchedWindow = state.windows[i]; - if (isWindowPresentLocked(touchedWindow.windowHandle)) { + if (mWindowInfos.isWindowPresent(touchedWindow.windowHandle)) { i++; continue; } @@ -5472,7 +5536,8 @@ void InputDispatcher::setInputWindowsLocked( [this, displayId, &touchedWindow](const PointerProperties& properties, float x, float y) REQUIRES(mLock) { const bool isStylus = properties.toolType == ToolType::STYLUS; - const ui::Transform displayTransform = getTransformLocked(displayId); + const ui::Transform displayTransform = + mWindowInfos.getDisplayTransform(displayId); const bool stillAcceptsTouch = windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(), displayId, x, y, isStylus, displayTransform); @@ -5494,7 +5559,7 @@ void InputDispatcher::setInputWindowsLocked( // Otherwise, they might stick around until the window handle is destroyed // which might not happen until the next GC. for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) { - if (!isWindowPresentLocked(oldWindowHandle)) { + if (!mWindowInfos.isWindowPresent(oldWindowHandle)) { if (DEBUG_FOCUS) { ALOGD("Window went away: %s", oldWindowHandle->getName().c_str()); } @@ -5571,7 +5636,7 @@ void InputDispatcher::setFocusedDisplay(ui::LogicalDisplayId displayId) { mFocusResolver.getFocusedWindowToken(mFocusedDisplayId); if (oldFocusedWindowToken != nullptr) { const auto windowHandle = - getWindowHandleLocked(oldFocusedWindowToken, mFocusedDisplayId); + mWindowInfos.findWindowHandle(oldFocusedWindowToken, mFocusedDisplayId); if (windowHandle == nullptr) { LOG(FATAL) << __func__ << ": Previously focused token did not have a window"; } @@ -5710,7 +5775,7 @@ bool InputDispatcher::focusedWindowIsOwnedByLocked(gui::Pid pid, gui::Uid uid) { if (focusedToken == nullptr) { return false; } - sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken); + sp<WindowInfoHandle> windowHandle = mWindowInfos.findWindowHandle(focusedToken); return isWindowOwnedBy(windowHandle, pid, uid); } @@ -5718,7 +5783,7 @@ bool InputDispatcher::recentWindowsAreOwnedByLocked(gui::Pid pid, gui::Uid uid) return std::find_if(mInteractionConnectionTokens.begin(), mInteractionConnectionTokens.end(), [&](const sp<IBinder>& connectionToken) REQUIRES(mLock) { const sp<WindowInfoHandle> windowHandle = - getWindowHandleLocked(connectionToken); + mWindowInfos.findWindowHandle(connectionToken); return isWindowOwnedBy(windowHandle, pid, uid); }) != mInteractionConnectionTokens.end(); } @@ -5789,7 +5854,8 @@ bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const s const DeviceId deviceId = *deviceIds.begin(); const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle; - const sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId); + const sp<WindowInfoHandle> toWindowHandle = + mWindowInfos.findWindowHandle(toToken, displayId); if (!toWindowHandle) { ALOGW("Cannot transfer touch because the transfer target window was not found."); return false; @@ -5896,7 +5962,8 @@ bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken sp<IBinder> fromToken; { // acquire lock std::scoped_lock _l(mLock); - sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(destChannelToken, displayId); + sp<WindowInfoHandle> toWindowHandle = + mWindowInfos.findWindowHandle(destChannelToken, displayId); if (toWindowHandle == nullptr) { ALOGW("Could not find window associated with token=%p on display %s", destChannelToken.get(), displayId.toString().c_str()); @@ -5955,7 +6022,7 @@ std::string InputDispatcher::dumpPointerCaptureStateLocked() const { std::string windowName = "None"; if (mWindowTokenWithPointerCapture) { const sp<WindowInfoHandle> captureWindowHandle = - getWindowHandleLocked(mWindowTokenWithPointerCapture); + mWindowInfos.findWindowHandle(mWindowTokenWithPointerCapture); windowName = captureWindowHandle ? captureWindowHandle->getName().c_str() : "token has capture without window"; } @@ -6004,31 +6071,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { mDragState->dump(dump, INDENT2); } - if (!mWindowHandlesByDisplay.empty()) { - for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) { - dump += StringPrintf(INDENT "Display: %s\n", displayId.toString().c_str()); - if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) { - const auto& displayInfo = it->second; - dump += StringPrintf(INDENT2 "logicalSize=%dx%d\n", displayInfo.logicalWidth, - displayInfo.logicalHeight); - displayInfo.transform.dump(dump, "transform", INDENT4); - } else { - dump += INDENT2 "No DisplayInfo found!\n"; - } - - if (!windowHandles.empty()) { - dump += INDENT2 "Windows:\n"; - for (size_t i = 0; i < windowHandles.size(); i++) { - dump += StringPrintf(INDENT3 "%zu: %s", i, - streamableToString(*windowHandles[i]).c_str()); - } - } else { - dump += INDENT2 "Windows: <none>\n"; - } - } - } else { - dump += INDENT "Displays: <none>\n"; - } + dump += addLinePrefix(mWindowInfos.dumpDisplayAndWindowInfo(), INDENT); if (!mGlobalMonitorsByDisplay.empty()) { for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) { @@ -6352,7 +6395,7 @@ void InputDispatcher::requestPointerCapture(const sp<IBinder>& windowToken, bool { // acquire lock std::scoped_lock _l(mLock); if (DEBUG_FOCUS) { - const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(windowToken); + const sp<WindowInfoHandle> windowHandle = mWindowInfos.findWindowHandle(windowToken); ALOGI("Request to %s Pointer Capture from: %s.", enabled ? "enable" : "disable", windowHandle != nullptr ? windowHandle->getName().c_str() : "token without window"); @@ -6492,7 +6535,7 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime, } traceWaitQueueLength(*connection); if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) { - const auto windowHandle = getWindowHandleLocked(connection->getToken()); + const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken()); // Only dispatch fallbacks if there is a window for the connection. if (windowHandle != nullptr) { const auto inputTarget = @@ -6556,7 +6599,7 @@ void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) ns2ms(currentWait), oldestEntry.eventEntry->getDescription().c_str()); sp<IBinder> connectionToken = connection->getToken(); - updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); + updateLastAnrStateLocked(mWindowInfos.findWindowHandle(connectionToken), reason); processConnectionUnresponsiveLocked(*connection, std::move(reason)); @@ -6664,7 +6707,7 @@ void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& conn // The connection is a window ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(), reason.c_str()); - const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken); + const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken); if (handle != nullptr) { pid = handle->getInfo()->ownerPid; } @@ -6682,7 +6725,7 @@ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connec pid = findMonitorPidByTokenLocked(connectionToken); } else { // The connection is a window - const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken); + const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken); if (handle != nullptr) { pid = handle->getInfo()->ownerPid; } @@ -6747,7 +6790,7 @@ std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptabl // Cancel the fallback key, but only if we still have a window for the channel. // It could have been removed during the policy call. if (*fallbackKeyCode != AKEYCODE_UNKNOWN) { - const auto windowHandle = getWindowHandleLocked(connection->getToken()); + const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken()); if (windowHandle != nullptr) { CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS, "application handled the original non-fallback key " @@ -6833,7 +6876,7 @@ std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptabl } } - const auto windowHandle = getWindowHandleLocked(connection->getToken()); + const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken()); if (windowHandle != nullptr) { CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS, "canceling fallback, policy no longer desires it", @@ -6975,7 +7018,7 @@ void InputDispatcher::setFocusedWindow(const FocusRequest& request) { std::scoped_lock _l(mLock); std::optional<FocusResolver::FocusChanges> changes = mFocusResolver.setFocusedWindow(request, - getWindowHandlesLocked( + mWindowInfos.getWindowHandlesForDisplay( ui::LogicalDisplayId{request.displayId})); ScopedSyntheticEventTracer traceContext(mTracer); if (changes) { @@ -6993,7 +7036,7 @@ void InputDispatcher::onFocusChangedLocked( if (changes.oldFocus) { const auto resolvedWindow = removedFocusedWindowHandle != nullptr ? removedFocusedWindowHandle - : getWindowHandleLocked(changes.oldFocus, changes.displayId); + : mWindowInfos.findWindowHandle(changes.oldFocus, changes.displayId); if (resolvedWindow == nullptr) { LOG(FATAL) << __func__ << ": Previously focused token did not have a window"; } @@ -7111,14 +7154,10 @@ void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) // Ensure that we have an entry created for all existing displays so that if a displayId has // no windows, we can tell that the windows were removed from the display. - for (const auto& [displayId, _] : mWindowHandlesByDisplay) { - handlesPerDisplay[displayId]; - } + mWindowInfos.forEachDisplayId( + [&](ui::LogicalDisplayId displayId) { handlesPerDisplay[displayId]; }); - mDisplayInfos.clear(); - for (const auto& displayInfo : update.displayInfos) { - mDisplayInfos.emplace(displayInfo.displayId, displayInfo); - } + mWindowInfos.setDisplayInfos(update.displayInfos); for (const auto& [displayId, handles] : handlesPerDisplay) { setInputWindowsLocked(handles, displayId); @@ -7265,7 +7304,7 @@ void InputDispatcher::transferWallpaperTouch( sp<WindowInfoHandle> InputDispatcher::findWallpaperWindowBelow( const sp<WindowInfoHandle>& windowHandle) const { const std::vector<sp<WindowInfoHandle>>& windowHandles = - getWindowHandlesLocked(windowHandle->getInfo()->displayId); + mWindowInfos.getWindowHandlesForDisplay(windowHandle->getInfo()->displayId); bool foundWindow = false; for (const sp<WindowInfoHandle>& otherHandle : windowHandles) { if (!foundWindow && otherHandle != windowHandle) { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index c6342c5876..e245acc147 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -368,24 +368,52 @@ private: }; sp<gui::WindowInfosListener> mWindowInfoListener; - std::unordered_map<ui::LogicalDisplayId /*displayId*/, - std::vector<sp<android::gui::WindowInfoHandle>>> - mWindowHandlesByDisplay GUARDED_BY(mLock); - std::unordered_map<ui::LogicalDisplayId /*displayId*/, android::gui::DisplayInfo> mDisplayInfos - GUARDED_BY(mLock); + class DispatcherWindowInfo { + public: + void setWindowHandlesForDisplay( + ui::LogicalDisplayId displayId, + std::vector<sp<android::gui::WindowInfoHandle>>&& windowHandles); + + void setDisplayInfos(const std::vector<android::gui::DisplayInfo>& displayInfos); + + void removeDisplay(ui::LogicalDisplayId displayId); + + // Get a reference to window handles by display, return an empty vector if not found. + const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesForDisplay( + ui::LogicalDisplayId displayId) const; + + void forEachWindowHandle( + std::function<void(const sp<android::gui::WindowInfoHandle>&)> f) const; + + void forEachDisplayId(std::function<void(ui::LogicalDisplayId)> f) const; + + // Get the transform for display, returns Identity-transform if display is missing. + ui::Transform getDisplayTransform(ui::LogicalDisplayId displayId) const; + + // Lookup for WindowInfoHandle from token and optionally a display-id. In cases where + // display-id is not provided lookup is done for all displays. + sp<android::gui::WindowInfoHandle> findWindowHandle( + const sp<IBinder>& windowHandleToken, + std::optional<ui::LogicalDisplayId> displayId = {}) const; + + bool isWindowPresent(const sp<android::gui::WindowInfoHandle>& windowHandle) const; + + std::string dumpDisplayAndWindowInfo() const; + + private: + std::unordered_map<ui::LogicalDisplayId /*displayId*/, + std::vector<sp<android::gui::WindowInfoHandle>>> + mWindowHandlesByDisplay; + std::unordered_map<ui::LogicalDisplayId /*displayId*/, android::gui::DisplayInfo> + mDisplayInfos; + }; + + DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock); + void setInputWindowsLocked( const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles, ui::LogicalDisplayId displayId) REQUIRES(mLock); - // Get a reference to window handles by display, return an empty vector if not found. - const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesLocked( - ui::LogicalDisplayId displayId) const REQUIRES(mLock); - ui::Transform getTransformLocked(ui::LogicalDisplayId displayId) const REQUIRES(mLock); - sp<android::gui::WindowInfoHandle> getWindowHandleLocked( - const sp<IBinder>& windowHandleToken, - std::optional<ui::LogicalDisplayId> displayId = {}) const REQUIRES(mLock); - bool isWindowPresentLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const - REQUIRES(mLock); sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked( ui::LogicalDisplayId displayId) const REQUIRES(mLock); bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window, |