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

Commit 6f6e2305 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Added input support for cloned layers"

parents 0cde87d4 af87b3e0
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -119,7 +119,11 @@ struct InputWindowInfo {
    /* These values are filled in by the WM and passed through SurfaceFlinger
    /* These values are filled in by the WM and passed through SurfaceFlinger
     * unless specified otherwise.
     * unless specified otherwise.
     */
     */
    // This value should NOT be used to uniquely identify the window. There may be different
    // input windows that have the same token.
    sp<IBinder> token;
    sp<IBinder> token;
    // This uniquely identifies the input window.
    int32_t id = 0;
    std::string name;
    std::string name;
    int32_t layoutParamsFlags;
    int32_t layoutParamsFlags;
    int32_t layoutParamsType;
    int32_t layoutParamsType;
@@ -203,6 +207,8 @@ public:


    sp<IBinder> getToken() const;
    sp<IBinder> getToken() const;


    int32_t getId() const { return mInfo.id; }

    sp<IBinder> getApplicationToken() {
    sp<IBinder> getApplicationToken() {
        return mInfo.applicationInfo.token;
        return mInfo.applicationInfo.token;
    }
    }
+2 −0
Original line number Original line Diff line number Diff line
@@ -73,6 +73,7 @@ status_t InputWindowInfo::write(Parcel& output) const {
    status_t s = output.writeStrongBinder(token);
    status_t s = output.writeStrongBinder(token);
    if (s != OK) return s;
    if (s != OK) return s;


    output.writeInt32(id);
    output.writeString8(String8(name.c_str()));
    output.writeString8(String8(name.c_str()));
    output.writeInt32(layoutParamsFlags);
    output.writeInt32(layoutParamsFlags);
    output.writeInt32(layoutParamsType);
    output.writeInt32(layoutParamsType);
@@ -116,6 +117,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) {
    }
    }


    ret.token = token;
    ret.token = token;
    ret.id = from.readInt32();
    ret.name = from.readString8().c_str();
    ret.name = from.readString8().c_str();
    ret.layoutParamsFlags = from.readInt32();
    ret.layoutParamsFlags = from.readInt32();
    ret.layoutParamsType = from.readInt32();
    ret.layoutParamsType = from.readInt32();
+2 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ TEST(InputWindowInfo, Parcelling) {
    sp<IBinder> touchableRegionCropHandle = new BBinder();
    sp<IBinder> touchableRegionCropHandle = new BBinder();
    InputWindowInfo i;
    InputWindowInfo i;
    i.token = new BBinder();
    i.token = new BBinder();
    i.id = 1;
    i.name = "Foobar";
    i.name = "Foobar";
    i.layoutParamsFlags = 7;
    i.layoutParamsFlags = 7;
    i.layoutParamsType = 39;
    i.layoutParamsType = 39;
@@ -72,6 +73,7 @@ TEST(InputWindowInfo, Parcelling) {
    p.setDataPosition(0);
    p.setDataPosition(0);
    InputWindowInfo i2 = InputWindowInfo::read(p);
    InputWindowInfo i2 = InputWindowInfo::read(p);
    ASSERT_EQ(i.token, i2.token);
    ASSERT_EQ(i.token, i2.token);
    ASSERT_EQ(i.id, i2.id);
    ASSERT_EQ(i.name, i2.name);
    ASSERT_EQ(i.name, i2.name);
    ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
    ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags);
    ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
    ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType);
+17 −5
Original line number Original line Diff line number Diff line
@@ -240,6 +240,18 @@ static bool removeByValue(std::unordered_map<K, V>& map, const V& value) {
    return removed;
    return removed;
}
}


static bool haveSameToken(const sp<InputWindowHandle>& first, const sp<InputWindowHandle>& second) {
    if (first == second) {
        return true;
    }

    if (first == nullptr || second == nullptr) {
        return false;
    }

    return first->getToken() == second->getToken();
}

// --- InputDispatcherThread ---
// --- InputDispatcherThread ---


class InputDispatcher::InputDispatcherThread : public Thread {
class InputDispatcher::InputDispatcherThread : public Thread {
@@ -3278,9 +3290,9 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked(
    // Since we compare the pointer of input window handles across window updates, we need
    // 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.
    // to make sure the handle object for the same window stays unchanged across updates.
    const std::vector<sp<InputWindowHandle>>& oldHandles = getWindowHandlesLocked(displayId);
    const std::vector<sp<InputWindowHandle>>& oldHandles = getWindowHandlesLocked(displayId);
    std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
    std::unordered_map<int32_t /*id*/, sp<InputWindowHandle>> oldHandlesById;
    for (const sp<InputWindowHandle>& handle : oldHandles) {
    for (const sp<InputWindowHandle>& handle : oldHandles) {
        oldHandlesByTokens[handle->getToken()] = handle;
        oldHandlesById[handle->getId()] = handle;
    }
    }


    std::vector<sp<InputWindowHandle>> newHandles;
    std::vector<sp<InputWindowHandle>> newHandles;
@@ -3311,8 +3323,8 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked(
            continue;
            continue;
        }
        }


        if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
        if (oldHandlesById.find(handle->getId()) != oldHandlesById.end()) {
            const sp<InputWindowHandle> oldHandle = oldHandlesByTokens.at(handle->getToken());
            const sp<InputWindowHandle>& oldHandle = oldHandlesById.at(handle->getId());
            oldHandle->updateFrom(handle);
            oldHandle->updateFrom(handle);
            newHandles.push_back(oldHandle);
            newHandles.push_back(oldHandle);
        } else {
        } else {
@@ -3370,7 +3382,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
        sp<InputWindowHandle> oldFocusedWindowHandle =
        sp<InputWindowHandle> oldFocusedWindowHandle =
                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);


        if (oldFocusedWindowHandle != newFocusedWindowHandle) {
        if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) {
            if (oldFocusedWindowHandle != nullptr) {
            if (oldFocusedWindowHandle != nullptr) {
                if (DEBUG_FOCUS) {
                if (DEBUG_FOCUS) {
                    ALOGD("Focus left window: %s in display %" PRId32,
                    ALOGD("Focus left window: %s in display %" PRId32,
+149 −0
Original line number Original line Diff line number Diff line
@@ -526,6 +526,7 @@ public:
        mInfo.applicationInfo = *inputApplicationHandle->getInfo();
        mInfo.applicationInfo = *inputApplicationHandle->getInfo();


        mInfo.token = token;
        mInfo.token = token;
        mInfo.id = 0;
        mInfo.name = name;
        mInfo.name = name;
        mInfo.layoutParamsFlags = 0;
        mInfo.layoutParamsFlags = 0;
        mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
        mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
@@ -564,6 +565,13 @@ public:


    void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
    void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }


    void setId(int32_t id) { mInfo.id = id; }

    void setWindowScale(float xScale, float yScale) {
        mInfo.windowXScale = xScale;
        mInfo.windowYScale = yScale;
    }

    void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
    void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
        consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
        consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
                     expectedFlags);
                     expectedFlags);
@@ -586,12 +594,21 @@ public:
                                     expectedFlags);
                                     expectedFlags);
    }
    }


    InputEvent* consume() {
        if (mInputReceiver == nullptr) {
            return nullptr;
        }
        return mInputReceiver->consume();
    }

    void assertNoEvents() {
    void assertNoEvents() {
        ASSERT_NE(mInputReceiver, nullptr)
        ASSERT_NE(mInputReceiver, nullptr)
                << "Call 'assertNoEvents' on a window with an InputReceiver";
                << "Call 'assertNoEvents' on a window with an InputReceiver";
        mInputReceiver->assertNoEvents();
        mInputReceiver->assertNoEvents();
    }
    }


    sp<IBinder> getToken() { return mInfo.token; }

private:
private:
    std::unique_ptr<FakeInputReceiver> mInputReceiver;
    std::unique_ptr<FakeInputReceiver> mInputReceiver;
};
};
@@ -667,6 +684,10 @@ static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLA
static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
                                           const std::vector<PointF>& points) {
                                           const std::vector<PointF>& points) {
    size_t pointerCount = points.size();
    size_t pointerCount = points.size();
    if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
        EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
    }

    PointerProperties pointerProperties[pointerCount];
    PointerProperties pointerProperties[pointerCount];
    PointerCoords pointerCoords[pointerCount];
    PointerCoords pointerCoords[pointerCount];


@@ -1291,4 +1312,132 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus,
    mFakePolicy->assertOnPointerDownWasNotCalled();
    mFakePolicy->assertOnPointerDownWasNotCalled();
}
}


// These tests ensures we can send touch events to a single client when there are multiple input
// windows that point to the same client token.
class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
    virtual void SetUp() override {
        InputDispatcherTest::SetUp();

        sp<FakeApplicationHandle> application = new FakeApplicationHandle();
        mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
                                        ADISPLAY_ID_DEFAULT);
        // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
        // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
        mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
                                      InputWindowInfo::FLAG_SPLIT_TOUCH);
        mWindow1->setId(0);
        mWindow1->setFrame(Rect(0, 0, 100, 100));

        mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
                                        ADISPLAY_ID_DEFAULT, mWindow1->getToken());
        mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
                                      InputWindowInfo::FLAG_SPLIT_TOUCH);
        mWindow2->setId(1);
        mWindow2->setFrame(Rect(100, 100, 200, 200));

        mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
    }

protected:
    sp<FakeWindowHandle> mWindow1;
    sp<FakeWindowHandle> mWindow2;

    // Helper function to convert the point from screen coordinates into the window's space
    static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
        float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
        float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
        return {x, y};
    }

    void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
                            const std::vector<PointF>& points) {
        std::string name = window->mName;
        InputEvent* event = window->consume();

        ASSERT_NE(nullptr, event) << name.c_str()
                                  << ": consumer should have returned non-NULL event.";

        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
                << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
                << " event, got " << inputEventTypeToString(event->getType()) << " event";

        const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
        EXPECT_EQ(expectedAction, motionEvent.getAction());

        for (size_t i = 0; i < points.size(); i++) {
            float expectedX = points[i].x;
            float expectedY = points[i].y;

            EXPECT_EQ(expectedX, motionEvent.getX(i))
                    << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
                    << ", got " << motionEvent.getX(i);
            EXPECT_EQ(expectedY, motionEvent.getY(i))
                    << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
                    << ", got " << motionEvent.getY(i);
        }
    }
};

TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
    // Touch Window 1
    PointF touchedPoint = {10, 10};
    PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);

    NotifyMotionArgs motionArgs =
            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                               ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});

    // Release touch on Window 1
    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);
    // consume the UP event
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});

    // Touch Window 2
    touchedPoint = {150, 150};
    expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);

    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);

    // Consuming from window1 since it's the window that has the InputReceiver
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
}

TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
    mWindow2->setWindowScale(0.5f, 0.5f);

    // Touch Window 1
    PointF touchedPoint = {10, 10};
    PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);

    NotifyMotionArgs motionArgs =
            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                               ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});

    // Release touch on Window 1
    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);
    // consume the UP event
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});

    // Touch Window 2
    touchedPoint = {150, 150};
    expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);

    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {touchedPoint});
    mDispatcher->notifyMotion(&motionArgs);

    // Consuming from window1 since it's the window that has the InputReceiver
    consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
}

} // namespace android::inputdispatcher
} // namespace android::inputdispatcher
Loading