Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd0fbcd1 authored by Garfield Tan's avatar Garfield Tan
Browse files

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
parent 023162b7
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -224,6 +224,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.
+4 −0
Original line number Diff line number Diff line
@@ -162,4 +162,8 @@ sp<IBinder> InputWindowHandle::getToken() const {
    return mInfo.token;
}

void InputWindowHandle::updateFrom(sp<InputWindowHandle> handle) {
    mInfo = handle->mInfo;
}

} // namespace android
+30 −8
Original line number Diff line number Diff line
@@ -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) {