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

Commit be98d993 authored by Antonio Kantek's avatar Antonio Kantek Committed by Automerger Merge Worker
Browse files

Merge "Add last interacted window check in setInTouchMode" into tm-dev am: f7c6df18

parents f85d4e18 f7c6df18
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -567,6 +567,17 @@ bool canReceiveForegroundTouches(const WindowInfo& info) {
    return !info.inputConfig.test(gui::WindowInfo::InputConfig::NOT_TOUCHABLE) && !info.isSpy();
}

bool isWindowOwnedBy(const sp<WindowInfoHandle>& windowHandle, int32_t pid, int32_t uid) {
    if (windowHandle == nullptr) {
        return false;
    }
    const WindowInfo* windowInfo = windowHandle->getInfo();
    if (pid == windowInfo->ownerPid && uid == windowInfo->ownerUid) {
        return true;
    }
    return false;
}

} // namespace

// --- InputDispatcher ---
@@ -4990,21 +5001,11 @@ bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid,
                  toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission));
        }
        if (!hasPermission) {
            const sp<IBinder> focusedToken =
                    mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);

            //  TODO(b/218541064): if no window is currently focused, then we need to check the last
            //      interacted window (within 1 second timeout). We should allow touch mode change
            //      if the last interacted window owner's pid/uid match the calling ones.
            if (focusedToken == nullptr) {
                return false;
            }
            const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
            if (windowHandle == nullptr) {
                return false;
            }
            const WindowInfo* windowInfo = windowHandle->getInfo();
            if (pid != windowInfo->ownerPid || uid != windowInfo->ownerUid) {
            if (!focusedWindowIsOwnedByLocked(pid, uid) &&
                !recentWindowsAreOwnedByLocked(pid, uid)) {
                ALOGD("Touch mode switch rejected, caller (pid=%d, uid=%d) doesn't own the focused "
                      "window nor none of the previously interacted window",
                      pid, uid);
                return false;
            }
        }
@@ -5022,6 +5023,24 @@ bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid,
    return true;
}

bool InputDispatcher::focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) {
    const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
    if (focusedToken == nullptr) {
        return false;
    }
    sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
    return isWindowOwnedBy(windowHandle, pid, uid);
}

bool InputDispatcher::recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) {
    return std::find_if(mInteractionConnectionTokens.begin(), mInteractionConnectionTokens.end(),
                        [&](const sp<IBinder>& connectionToken) REQUIRES(mLock) {
                            const sp<WindowInfoHandle> windowHandle =
                                    getWindowHandleLocked(connectionToken);
                            return isWindowOwnedBy(windowHandle, pid, uid);
                        }) != mInteractionConnectionTokens.end();
}

void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
    if (opacity < 0 || opacity > 1) {
        LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1");
+6 −1
Original line number Diff line number Diff line
@@ -433,7 +433,8 @@ private:
    // Dispatcher state at time of last ANR.
    std::string mLastAnrState GUARDED_BY(mLock);

    // The connection tokens of the channels that the user last interacted, for debugging
    // The connection tokens of the channels that the user last interacted (used for debugging and
    // when switching touch mode state).
    std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> mInteractionConnectionTokens
            GUARDED_BY(mLock);
    void updateInteractionTokensLocked(const EventEntry& entry,
@@ -677,6 +678,10 @@ private:
    void traceOutboundQueueLength(const Connection& connection);
    void traceWaitQueueLength(const Connection& connection);

    // Check window ownership
    bool focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);
    bool recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);

    sp<InputReporterInterface> mReporter;
};

+22 −2
Original line number Diff line number Diff line
@@ -6336,8 +6336,11 @@ protected:
        mWindow->consumeFocusEvent(true);

        // Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
        mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
                                    INJECTOR_UID, /* hasPermission */ true);
        if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
                                        INJECTOR_UID, /* hasPermission */ true)) {
            mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
            mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
        }
    }

    void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
@@ -6382,6 +6385,23 @@ TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTou
    mSecondWindow->assertNoEvents();
}

TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
    // Interact with the window first.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
            << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
    mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);

    // Then remove focus.
    mWindow->setFocusable(false);
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});

    // Assert that caller can switch touch mode by owning one of the last interacted window.
    const WindowInfo& windowInfo = *mWindow->getInfo();
    ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
                                            windowInfo.ownerPid, windowInfo.ownerUid,
                                            /* hasPermission= */ false));
}

class InputDispatcherSpyWindowTest : public InputDispatcherTest {
public:
    sp<FakeWindowHandle> createSpy() {