From b3ad35c924daa36a3d1164dabcb7eea6515589f4 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Fri, 5 Apr 2019 10:50:52 -0700 Subject: Refactor setInputWindows The logic for the actual window update is now factored out into a separate function. Otherwise, setInputWindows was too long and tough to reason about. There should be no functional change in this CL. Bug: none Test: atest -a inputflinger_tests Change-Id: I49c2eda5178de79de23f772ffc279249ca4402e8 --- services/inputflinger/InputDispatcher.cpp | 152 +++++++++++++++--------------- services/inputflinger/InputDispatcher.h | 7 ++ 2 files changed, 85 insertions(+), 74 deletions(-) diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index 7324c28a81..13de53dc20 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -236,9 +236,17 @@ static void dumpRegion(std::string& dump, const Region& region) { } } -template -static T getValueByKey(std::unordered_map& map, U key) { - typename std::unordered_map::const_iterator it = map.find(key); +/** + * Find the entry in std::unordered_map by key, and return it. + * If the entry is not found, return a default constructed entry. + * + * Useful when the entries are vectors, since an empty vector will be returned + * if the entry is not found. + * Also useful when the entries are sp<>. If an entry is not found, nullptr is returned. + */ +template +static T getValueByKey(const std::unordered_map& map, U key) { + auto it = map.find(key); return it != map.end() ? it->second : T{}; } @@ -3028,14 +3036,7 @@ void InputDispatcher::decrementPendingForegroundDispatches(EventEntry* entry) { std::vector> InputDispatcher::getWindowHandlesLocked( int32_t displayId) const { - std::unordered_map>>::const_iterator it = - mWindowHandlesByDisplay.find(displayId); - if(it != mWindowHandlesByDisplay.end()) { - return it->second; - } - - // Return an empty one if nothing found. - return std::vector>(); + return getValueByKey(mWindowHandlesByDisplay, displayId); } sp InputDispatcher::getWindowHandleLocked( @@ -3077,6 +3078,63 @@ sp InputDispatcher::getInputChannelLocked(const sp& token return mInputChannelsByToken.at(token); } +void InputDispatcher::updateWindowHandlesForDisplayLocked( + const std::vector>& inputWindowHandles, int32_t displayId) { + if (inputWindowHandles.empty()) { + // Remove all handles on a display if there are no windows left. + mWindowHandlesByDisplay.erase(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>& oldHandles = getWindowHandlesLocked(displayId); + std::unordered_map, sp, IBinderHash> oldHandlesByTokens; + for (const sp& handle : oldHandles) { + oldHandlesByTokens[handle->getToken()] = handle; + } + + std::vector> newHandles; + for (const sp& handle : inputWindowHandles) { + if (!handle->updateInfo()) { + // handle no longer valid + continue; + } + + const InputWindowInfo* info = handle->getInfo(); + if ((getInputChannelLocked(handle->getToken()) == nullptr && + info->portalToDisplayId == ADISPLAY_ID_NONE)) { + const bool noInputChannel = + info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; + const bool canReceiveInput = + !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) || + !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE); + if (canReceiveInput && !noInputChannel) { + ALOGE("Window handle %s has no registered input channel", + handle->getName().c_str()); + } + continue; + } + + if (info->displayId != displayId) { + ALOGE("Window %s updated by wrong display %d, should belong to display %d", + handle->getName().c_str(), displayId, info->displayId); + continue; + } + + if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) { + const sp oldHandle = oldHandlesByTokens.at(handle->getToken()); + oldHandle->updateFrom(handle); + newHandles.push_back(oldHandle); + } else { + newHandles.push_back(handle); + } + } + + // Insert or replace + mWindowHandlesByDisplay[displayId] = newHandles; +} + /** * Called from InputManagerService, update window handle list by displayId that can receive input. * A window handle contains information about InputChannel, Touch Region, Types, Focused,... @@ -3096,73 +3154,19 @@ void InputDispatcher::setInputWindows(const std::vector>& const std::vector> oldWindowHandles = getWindowHandlesLocked(displayId); + updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId); + sp newFocusedWindowHandle = nullptr; bool foundHoveredWindow = false; - - if (inputWindowHandles.empty()) { - // Remove all handles on a display if there are no windows left. - mWindowHandlesByDisplay.erase(displayId); - } else { - // 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>& oldHandles = - mWindowHandlesByDisplay[displayId]; - std::unordered_map, sp, IBinderHash> oldHandlesByTokens; - for (const sp& handle : oldHandles) { - oldHandlesByTokens[handle->getToken()] = handle; - } - - std::vector> newHandles; - for (const sp& handle : inputWindowHandles) { - if (!handle->updateInfo()) { - // handle no longer valid - continue; - } - const InputWindowInfo* info = handle->getInfo(); - - if ((getInputChannelLocked(handle->getToken()) == nullptr && - info->portalToDisplayId == ADISPLAY_ID_NONE)) { - const bool noInputChannel = - info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; - const bool canReceiveInput = - !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) || - !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE); - if (canReceiveInput && !noInputChannel) { - ALOGE("Window handle %s has no registered input channel", - handle->getName().c_str()); - } - continue; - } - - if (info->displayId != displayId) { - ALOGE("Window %s updated by wrong display %d, should belong to display %d", - handle->getName().c_str(), displayId, info->displayId); - continue; - } - - if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) { - const sp oldHandle = - oldHandlesByTokens.at(handle->getToken()); - oldHandle->updateFrom(handle); - newHandles.push_back(oldHandle); - } else { - newHandles.push_back(handle); - } + for (const sp& windowHandle : getWindowHandlesLocked(displayId)) { + // Set newFocusedWindowHandle to the top most focused window instead of the last one + if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus && + windowHandle->getInfo()->visible) { + newFocusedWindowHandle = windowHandle; } - - for (const sp& windowHandle : newHandles) { - // Set newFocusedWindowHandle to the top most focused window instead of the last one - if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus - && windowHandle->getInfo()->visible) { - newFocusedWindowHandle = windowHandle; - } - if (windowHandle == mLastHoverWindowHandle) { - foundHoveredWindow = true; - } + if (windowHandle == mLastHoverWindowHandle) { + foundHoveredWindow = true; } - - // Insert or replace - mWindowHandlesByDisplay[displayId] = newHandles; } if (!foundHoveredWindow) { diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h index 3735a0bcc6..183efa930b 100644 --- a/services/inputflinger/InputDispatcher.h +++ b/services/inputflinger/InputDispatcher.h @@ -1006,6 +1006,13 @@ private: sp getInputChannelLocked(const sp& windowToken) const REQUIRES(mLock); bool hasWindowHandleLocked(const sp& windowHandle) const REQUIRES(mLock); + /* + * Validate and update InputWindowHandles for a given display. + */ + void updateWindowHandlesForDisplayLocked( + const std::vector>& inputWindowHandles, int32_t displayId) + REQUIRES(mLock); + // Focus tracking for keys, trackball, etc. std::unordered_map> mFocusedWindowHandlesByDisplay GUARDED_BY(mLock); -- cgit v1.2.3-59-g8ed1b