summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Garfield Tan <xutan@google.com> 2018-11-30 12:45:03 -0800
committer Garfield Tan <xutan@google.com> 2018-12-04 21:15:40 +0000
commitbd0fbcd1f37f4e7e2e505cf5e5ede0fe52a3767c (patch)
treef061254868e6dd39cc1c2086461ece082fa385c5
parent023162b7e6872c42552de35380d348ab3e785fac (diff)
Keep instance of BinderInputWindow for the same token.
Some code in InputDispatcher uses pointer value comparison to track if a BinderInputWindow is the same. Therefore just keep the initial instance and reuse that for every update. This is better than changing all pointer comparisons to token comparisons because it would be hard to make sure every comparison is changed. Later we could simply drop InputWindowHandle and use InputWindowInfo value instead. It would also be better if it could implement move constructor so that we can use move semantics. Bug: 120289807 Bug: 120463595 Bug: 120481017 Test: Verified that input focus stops constantly changing by inpecting logcat after enabling DEBUG_FOCUS in InputDispatcher.cpp. Freeform drag-resize works with a workaround to another race condition. Change-Id: I34bbf8c076373ef23494f858536c5188eff95abd
-rw-r--r--include/input/InputWindow.h5
-rw-r--r--libs/input/InputWindow.cpp4
-rw-r--r--services/inputflinger/InputDispatcher.cpp38
3 files changed, 39 insertions, 8 deletions
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 8dd95cfb9a..2b8cc57c05 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -225,6 +225,11 @@ public:
virtual bool updateInfo() = 0;
/**
+ * Updates from another input window handle.
+ */
+ void updateFrom(const sp<InputWindowHandle> handle);
+
+ /**
* Releases the channel used by the associated information when it is
* no longer needed.
*/
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 556a005580..aa1371fdc9 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -162,4 +162,8 @@ sp<IBinder> InputWindowHandle::getToken() const {
return mInfo.token;
}
+void InputWindowHandle::updateFrom(sp<InputWindowHandle> handle) {
+ mInfo = handle->mInfo;
+}
+
} // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 12d91bbd68..a498fa154c 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3077,22 +3077,44 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& input
// Remove all handles on a display if there are no windows left.
mWindowHandlesByDisplay.erase(displayId);
} else {
- size_t numWindows = inputWindowHandles.size();
+ // 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 Vector<sp<InputWindowHandle>>& oldHandles = mWindowHandlesByDisplay[displayId];
+ std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
+ for (size_t i = 0; i < oldHandles.size(); i++) {
+ const sp<InputWindowHandle>& handle = oldHandles.itemAt(i);
+ oldHandlesByTokens[handle->getToken()] = handle;
+ }
+
+ const size_t numWindows = inputWindowHandles.size();
+ Vector<sp<InputWindowHandle>> newHandles;
for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = inputWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || getInputChannelLocked(windowHandle->getToken()) == nullptr) {
+ const sp<InputWindowHandle>& handle = inputWindowHandles.itemAt(i);
+ if (!handle->updateInfo() || getInputChannelLocked(handle->getToken()) == nullptr) {
ALOGE("Window handle %s has no registered input channel",
- windowHandle->getName().c_str());
+ handle->getName().c_str());
continue;
}
- if (windowHandle->getInfo()->displayId != displayId) {
+ if (handle->getInfo()->displayId != displayId) {
ALOGE("Window %s updated by wrong display %d, should belong to display %d",
- windowHandle->getName().c_str(), displayId,
- windowHandle->getInfo()->displayId);
+ handle->getName().c_str(), displayId,
+ handle->getInfo()->displayId);
continue;
}
+ if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
+ const sp<InputWindowHandle> oldHandle =
+ oldHandlesByTokens.at(handle->getToken());
+ oldHandle->updateFrom(handle);
+ newHandles.push_back(oldHandle);
+ } else {
+ newHandles.push_back(handle);
+ }
+ }
+
+ for (size_t i = 0; i < newHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = newHandles.itemAt(i);
if (windowHandle->getInfo()->hasFocus && windowHandle->getInfo()->visible) {
newFocusedWindowHandle = windowHandle;
}
@@ -3102,7 +3124,7 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& input
}
// Insert or replace
- mWindowHandlesByDisplay[displayId] = inputWindowHandles;
+ mWindowHandlesByDisplay[displayId] = newHandles;
}
if (!foundHoveredWindow) {