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

Commit 5e469d58 authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Fix WM input limitations on secondary displays (2/4)"

parents c299c9ec b92218b3
Loading
Loading
Loading
Loading
+140 −65
Original line number Diff line number Diff line
@@ -515,9 +515,10 @@ void InputDispatcher::addRecentEventLocked(EventEntry* entry) {
sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
        int32_t x, int32_t y) {
    // Traverse windows from front to back to find touched window.
    size_t numWindows = mWindowHandles.size();
    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
    size_t numWindows = windowHandles.size();
    for (size_t i = 0; i < numWindows; i++) {
        sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
        sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
        if (windowInfo->displayId == displayId) {
            int32_t flags = windowInfo->layoutParamsFlags;
@@ -1247,9 +1248,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
        bool isTouchModal = false;

        // Traverse windows from front to back to find touched window and outside targets.
        size_t numWindows = mWindowHandles.size();
        const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
        size_t numWindows = windowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
            sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
            const InputWindowInfo* windowInfo = windowHandle->getInfo();
            if (windowInfo->displayId != displayId) {
                continue; // wrong display
@@ -1472,8 +1474,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
        sp<InputWindowHandle> foregroundWindowHandle =
                mTempTouchState.getFirstForegroundWindowHandle();
        if (foregroundWindowHandle->getInfo()->hasWallpaper) {
            for (size_t i = 0; i < mWindowHandles.size(); i++) {
                sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
            const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
            size_t numWindows = windowHandles.size();
            for (size_t i = 0; i < numWindows; i++) {
                sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
                const InputWindowInfo* info = windowHandle->getInfo();
                if (info->displayId == displayId
                        && windowHandle->getInfo()->layoutParamsType
@@ -1658,9 +1662,10 @@ bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& wind
bool InputDispatcher::isWindowObscuredAtPointLocked(
        const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
    int32_t displayId = windowHandle->getInfo()->displayId;
    size_t numWindows = mWindowHandles.size();
    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
    size_t numWindows = windowHandles.size();
    for (size_t i = 0; i < numWindows; i++) {
        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
        sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
        if (otherHandle == windowHandle) {
            break;
        }
@@ -1678,10 +1683,11 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(

bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
    int32_t displayId = windowHandle->getInfo()->displayId;
    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
    const InputWindowInfo* windowInfo = windowHandle->getInfo();
    size_t numWindows = mWindowHandles.size();
    size_t numWindows = windowHandles.size();
    for (size_t i = 0; i < numWindows; i++) {
        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
        sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
        if (otherHandle == windowHandle) {
            break;
        }
@@ -2909,47 +2915,101 @@ void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* ent
    }
}

Vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(int32_t displayId) const {
    std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>>::const_iterator it =
        mWindowHandlesByDisplay.find(displayId);
    if(it != mWindowHandlesByDisplay.end()) {
        return it->second;
    }

    // Return an empty one if nothing found.
    return Vector<sp<InputWindowHandle>>();
}

sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
        const sp<InputChannel>& inputChannel) const {
    size_t numWindows = mWindowHandles.size();
    for (auto& it : mWindowHandlesByDisplay) {
        const Vector<sp<InputWindowHandle>> windowHandles = it.second;
        size_t numWindows = windowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
        const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
            const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
            if (windowHandle->getInputChannel() == inputChannel) {
                return windowHandle;
            }
        }
    }
    return nullptr;
}

bool InputDispatcher::hasWindowHandleLocked(
        const sp<InputWindowHandle>& windowHandle) const {
    size_t numWindows = mWindowHandles.size();
    for (auto& it : mWindowHandlesByDisplay) {
        const Vector<sp<InputWindowHandle>> windowHandles = it.second;
        size_t numWindows = windowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
        if (mWindowHandles.itemAt(i) == windowHandle) {
            if (windowHandles.itemAt(i) == windowHandle) {
                if (windowHandle->getInfo()->displayId != it.first) {
                    ALOGE("Found window %s in display %d, but it should belong to display %d",
                        windowHandle->getName().c_str(), it.first,
                        windowHandle->getInfo()->displayId);
                }
                return true;
            }
        }
    }
    return false;
}

void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
/**
 * Called from InputManagerService, update window handle list by displayId that can receive input.
 * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
 * If set an empty list, remove all handles from the specific display.
 * For focused handle, check if need to change and send a cancel event to previous one.
 * For removed handle, check if need to send a cancel event if already in touch.
 */
void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
        int32_t displayId) {
#if DEBUG_FOCUS
    ALOGD("setInputWindows");
#endif
    { // acquire lock
        AutoMutex _l(mLock);

        Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
        mWindowHandles = inputWindowHandles;
        // Copy old handles for release if they are no longer present.
        const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);

        // TODO(b/111361570): multi-display focus, one focus window per display.
        sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
        // Reset newFocusedWindowHandle to nullptr if current display own the focus window,
        // that will be updated below when going through all window handles in current display.
        // And if list of window handles becomes empty then it will be updated by other display.
        if (mFocusedWindowHandle != nullptr) {
            const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
            if (info == nullptr || info->displayId == displayId) {
                newFocusedWindowHandle = nullptr;
            }
        }

        sp<InputWindowHandle> newFocusedWindowHandle;
        bool foundHoveredWindow = false;
        for (size_t i = 0; i < mWindowHandles.size(); i++) {
            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);

        if (inputWindowHandles.isEmpty()) {
            // Remove all handles on a display if there are no windows left.
            mWindowHandlesByDisplay.erase(displayId);
        } else {
            size_t numWindows = inputWindowHandles.size();
            for (size_t i = 0; i < numWindows; i++) {
                const sp<InputWindowHandle>& windowHandle = inputWindowHandles.itemAt(i);
                if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
                mWindowHandles.removeAt(i--);
                    continue;
                }

                if (windowHandle->getInfo()->displayId != displayId) {
                    ALOGE("Window %s updated by wrong display %d, should belong to display %d",
                        windowHandle->getName().c_str(), displayId,
                        windowHandle->getInfo()->displayId);
                    continue;
                }

                if (windowHandle->getInfo()->hasFocus) {
                    newFocusedWindowHandle = windowHandle;
                }
@@ -2958,10 +3018,15 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
                }
            }

            // Insert or replace
            mWindowHandlesByDisplay[displayId] = inputWindowHandles;
        }

        if (!foundHoveredWindow) {
            mLastHoverWindowHandle = nullptr;
        }

        // TODO(b/111361570): multi-display focus, one focus in all display in current.
        if (mFocusedWindowHandle != newFocusedWindowHandle) {
            if (mFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
@@ -2985,8 +3050,9 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
            mFocusedWindowHandle = newFocusedWindowHandle;
        }

        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
        if (stateIndex >= 0) {
            TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
            for (size_t i = 0; i < state.windows.size(); ) {
                TouchedWindow& touchedWindow = state.windows.editItemAt(i);
                if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
@@ -3013,7 +3079,8 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
        // This ensures that unused input channels are released promptly.
        // Otherwise, they might stick around until the window handle is destroyed
        // which might not happen until the next GC.
        for (size_t i = 0; i < oldWindowHandles.size(); i++) {
        size_t numWindows = oldWindowHandles.size();
        for (size_t i = 0; i < numWindows; i++) {
            const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
            if (!hasWindowHandleLocked(oldWindowHandle)) {
#if DEBUG_FOCUS
@@ -3266,13 +3333,17 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
        dump += INDENT "TouchStates: <no displays touched>\n";
    }

    if (!mWindowHandles.isEmpty()) {
        dump += INDENT "Windows:\n";
        for (size_t i = 0; i < mWindowHandles.size(); i++) {
            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
    if (!mWindowHandlesByDisplay.empty()) {
       for (auto& it : mWindowHandlesByDisplay) {
            const Vector<sp<InputWindowHandle>> windowHandles = it.second;
            dump += StringPrintf(INDENT "Display: %d\n", it.first);
            if (!windowHandles.isEmpty()) {
                dump += INDENT2 "Windows:\n";
                for (size_t i = 0; i < windowHandles.size(); i++) {
                    const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
                    const InputWindowInfo* windowInfo = windowHandle->getInfo();

            dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
                    dump += StringPrintf(INDENT3 "%zu: name='%s', displayId=%d, "
                            "paused=%s, hasFocus=%s, hasWallpaper=%s, "
                            "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                            "frame=[%d,%d][%d,%d], scale=%f, "
@@ -3295,7 +3366,11 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
                            windowInfo->dispatchingTimeout / 1000000.0);
                }
            } else {
        dump += INDENT "Windows: <none>\n";
                dump += INDENT2 "Windows: <none>\n";
            }
        }
    } else {
        dump += INDENT "Displays: <none>\n";
    }

    if (!mMonitoringChannels.isEmpty()) {
+8 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <stddef.h>
#include <unistd.h>
#include <limits.h>
#include <unordered_map>

#include "InputWindow.h"
#include "InputApplication.h"
@@ -307,7 +308,8 @@ public:
     *
     * This method may be called on any thread (usually by the input manager).
     */
    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
            int32_t displayId) = 0;

    /* Sets the focused application.
     *
@@ -387,7 +389,8 @@ public:
            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
            uint32_t policyFlags);

    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
            int32_t displayId);
    virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
    virtual void setInputDispatchMode(bool enabled, bool frozen);
    virtual void setInputFilterEnabled(bool enabled);
@@ -956,8 +959,9 @@ private:
    bool mDispatchFrozen;
    bool mInputFilterEnabled;

    Vector<sp<InputWindowHandle> > mWindowHandles;

    std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
    // Get window handles by display, return an empty vector if not found.
    Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
    sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;

+300 −0

File changed.

Preview size limit exceeded, changes collapsed.