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

Commit f1035d4f authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Move focus dispatch to input (1/2)

Input now tells the apps when they have focus.
When a focus change has been detected, we enqueue a FocusEntry into the
dispatcher queue. It will be sent to the app via the socket.

At the same time, we tell the apps the current state of the touch mode.

Bug: 70668286
Test: atest libinput_tests inputflinger_tests
Change-Id: Icefb9383ba8424162d739c9e981bd1dd01cc7941
parent 838817f1
Loading
Loading
Loading
Loading
+61 −7
Original line number Diff line number Diff line
@@ -112,22 +112,31 @@ public:
        if (consumed != OK) {
            return nullptr;
        }
        mInputConsumer->sendFinishedSignal(seqId, true);
        status_t status = mInputConsumer->sendFinishedSignal(seqId, true);
        EXPECT_EQ(OK, status) << "Could not send finished signal";
        return ev;
    }

    void assertFocusChange(bool hasFocus) {
        InputEvent *ev = consumeEvent();
        ASSERT_NE(ev, nullptr);
        ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType());
        FocusEvent *focusEvent = static_cast<FocusEvent *>(ev);
        EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
    }

    void expectTap(int x, int y) {
        InputEvent* ev = consumeEvent();
        EXPECT_TRUE(ev != nullptr);
        EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
        ASSERT_NE(ev, nullptr);
        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
        MotionEvent* mev = static_cast<MotionEvent*>(ev);
        EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
        EXPECT_EQ(x, mev->getX(0));
        EXPECT_EQ(y, mev->getY(0));

        ev = consumeEvent();
        EXPECT_TRUE(ev != nullptr);
        EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
        ASSERT_NE(ev, nullptr);
        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType());
        mev = static_cast<MotionEvent*>(ev);
        EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
    }
@@ -212,7 +221,7 @@ public:
        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());

        const auto display = mComposerClient->getInternalDisplayToken();
        ASSERT_FALSE(display == nullptr);
        ASSERT_NE(display, nullptr);

        DisplayInfo info;
        ASSERT_EQ(NO_ERROR, mComposerClient->getDisplayInfo(display, &info));
@@ -259,18 +268,28 @@ void injectTap(int x, int y) {
TEST_F(InputSurfacesTest, can_receive_input) {
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
    surface->showAt(100, 100);
    surface->assertFocusChange(true);

    injectTap(101, 101);

    EXPECT_TRUE(surface->consumeEvent() != nullptr);
    EXPECT_NE(surface->consumeEvent(), nullptr);
}

/**
 * Set up two surfaces side-by-side. Tap each surface.
 * Next, swap the positions of the two surfaces. Inject tap into the two
 * original locations. Ensure that the tap is received by the surfaces in the
 * reverse order.
 */
TEST_F(InputSurfacesTest, input_respects_positioning) {
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
    surface->showAt(100, 100);
    surface->assertFocusChange(true);

    std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
    surface2->showAt(200, 200);
    surface->assertFocusChange(false);
    surface2->assertFocusChange(true);

    injectTap(201, 201);
    surface2->expectTap(1, 1);
@@ -297,11 +316,16 @@ TEST_F(InputSurfacesTest, input_respects_layering) {
    std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);

    surface->showAt(10, 10);
    surface->assertFocusChange(true);
    surface2->showAt(10, 10);
    surface->assertFocusChange(false);
    surface2->assertFocusChange(true);

    surface->doTransaction([](auto &t, auto &sc) {
         t.setLayer(sc, LAYER_BASE + 1);
    });
    surface2->assertFocusChange(false);
    surface->assertFocusChange(true);

    injectTap(11, 11);
    surface->expectTap(1, 1);
@@ -309,6 +333,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) {
    surface2->doTransaction([](auto &t, auto &sc) {
         t.setLayer(sc, LAYER_BASE + 1);
    });
    surface2->assertFocusChange(true);
    surface->assertFocusChange(false);

    injectTap(11, 11);
    surface2->expectTap(1, 1);
@@ -316,6 +342,8 @@ TEST_F(InputSurfacesTest, input_respects_layering) {
    surface2->doTransaction([](auto &t, auto &sc) {
         t.hide(sc);
    });
    surface2->assertFocusChange(false);
    surface->assertFocusChange(true);

    injectTap(11, 11);
    surface->expectTap(1, 1);
@@ -328,9 +356,12 @@ TEST_F(InputSurfacesTest, input_respects_surface_insets) {
    std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
    bgSurface->showAt(100, 100);
    bgSurface->assertFocusChange(true);

    fgSurface->mInputInfo.surfaceInset = 5;
    fgSurface->showAt(100, 100);
    fgSurface->assertFocusChange(true);
    bgSurface->assertFocusChange(false);

    injectTap(106, 106);
    fgSurface->expectTap(1, 1);
@@ -344,9 +375,12 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) {
    std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
    std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100);
    parentSurface->showAt(100, 100);
    parentSurface->assertFocusChange(true);

    childSurface->mInputInfo.surfaceInset = 10;
    childSurface->showAt(100, 100);
    childSurface->assertFocusChange(true);
    parentSurface->assertFocusChange(false);

    childSurface->doTransaction([&](auto &t, auto &sc) {
        t.setPosition(sc, -5, -5);
@@ -365,9 +399,12 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) {
    std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
    bgSurface->showAt(100, 100);
    bgSurface->assertFocusChange(true);

    fgSurface->mInputInfo.surfaceInset = 5;
    fgSurface->showAt(100, 100);
    bgSurface->assertFocusChange(false);
    fgSurface->assertFocusChange(true);

    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });

@@ -384,6 +421,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
    // In case we pass the very big inset without any checking.
    fgSurface->mInputInfo.surfaceInset = INT32_MAX;
    fgSurface->showAt(100, 100);
    fgSurface->assertFocusChange(true);

    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });

@@ -400,6 +438,7 @@ TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
        t.setTransparentRegionHint(sc, transparentRegion);
    });
    surface->showAt(100, 100);
    surface->assertFocusChange(true);
    injectTap(101, 101);
    surface->expectTap(1, 1);
}
@@ -414,7 +453,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
            InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);

    bgSurface->showAt(10, 10);
    bgSurface->assertFocusChange(true);
    bufferSurface->showAt(10, 10);
    bgSurface->assertFocusChange(false);
    bufferSurface->assertFocusChange(true);

    injectTap(11, 11);
    bufferSurface->expectTap(1, 1);
@@ -431,7 +473,10 @@ TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
    postBuffer(bufferSurface->mSurfaceControl);

    bgSurface->showAt(10, 10);
    bgSurface->assertFocusChange(true);
    bufferSurface->showAt(10, 10);
    bufferSurface->assertFocusChange(true);
    bgSurface->assertFocusChange(false);

    injectTap(11, 11);
    bufferSurface->expectTap(1, 1);
@@ -447,7 +492,10 @@ TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);

    bgSurface->showAt(10, 10);
    bgSurface->assertFocusChange(true);
    fgSurface->showAt(10, 10);
    bgSurface->assertFocusChange(false);
    fgSurface->assertFocusChange(true);

    injectTap(11, 11);
    fgSurface->expectTap(1, 1);
@@ -464,12 +512,17 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
            InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);

    bgSurface->showAt(10, 10);
    bgSurface->assertFocusChange(true);
    containerSurface->showAt(10, 10);
    bgSurface->assertFocusChange(false);
    containerSurface->assertFocusChange(true);

    injectTap(11, 11);
    containerSurface->expectTap(1, 1);

    containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); });
    containerSurface->assertFocusChange(false);
    bgSurface->assertFocusChange(true);

    injectTap(11, 11);
    bgSurface->expectTap(1, 1);
@@ -478,6 +531,7 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
TEST_F(InputSurfacesTest, input_respects_outscreen) {
    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
    surface->showAt(-1, -1);
    surface->assertFocusChange(true);

    injectTap(0, 0);
    surface->expectTap(1, 1);
+15 −0
Original line number Diff line number Diff line
@@ -111,6 +111,21 @@ void DeviceResetEntry::appendDescription(std::string& msg) const {
    msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
}

// --- FocusEntry ---

// Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries
FocusEntry::FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken,
                       bool hasFocus)
      : EventEntry(sequenceNum, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER),
        connectionToken(connectionToken),
        hasFocus(hasFocus) {}

FocusEntry::~FocusEntry() {}

void FocusEntry::appendDescription(std::string& msg) const {
    msg += StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false");
}

// --- KeyEntry ---

KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+20 −1
Original line number Diff line number Diff line
@@ -33,7 +33,13 @@ namespace android::inputdispatcher {
constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;

struct EventEntry {
    enum class Type { CONFIGURATION_CHANGED, DEVICE_RESET, KEY, MOTION };
    enum class Type {
        CONFIGURATION_CHANGED,
        DEVICE_RESET,
        FOCUS,
        KEY,
        MOTION,
    };

    static const char* typeToString(Type type) {
        switch (type) {
@@ -41,6 +47,8 @@ struct EventEntry {
                return "CONFIGURATION_CHANGED";
            case Type::DEVICE_RESET:
                return "DEVICE_RESET";
            case Type::FOCUS:
                return "FOCUS";
            case Type::KEY:
                return "KEY";
            case Type::MOTION:
@@ -102,6 +110,17 @@ protected:
    virtual ~DeviceResetEntry();
};

struct FocusEntry : EventEntry {
    sp<IBinder> connectionToken;
    bool hasFocus;

    FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus);
    virtual void appendDescription(std::string& msg) const;

protected:
    virtual ~FocusEntry();
};

struct KeyEntry : EventEntry {
    int32_t deviceId;
    uint32_t source;
+53 −1
Original line number Diff line number Diff line
@@ -469,6 +469,14 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
            break;
        }

        case EventEntry::Type::FOCUS: {
            FocusEntry* typedEntry = static_cast<FocusEntry*>(mPendingEvent);
            dispatchFocusLocked(currentTime, typedEntry);
            done = true;
            dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
            break;
        }

        case EventEntry::Type::KEY: {
            KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
            if (isAppSwitchDue) {
@@ -573,7 +581,8 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
            break;
        }
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
        case EventEntry::Type::DEVICE_RESET:
        case EventEntry::Type::FOCUS: {
            // nothing to do
            break;
        }
@@ -712,6 +721,7 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason
            }
            break;
        }
        case EventEntry::Type::FOCUS:
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            LOG_ALWAYS_FATAL("Should not drop %s events", EventEntry::typeToString(entry.type));
@@ -872,6 +882,25 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceReset
    return true;
}

void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) {
    FocusEntry* focusEntry =
            new FocusEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, now(), window.getToken(), hasFocus);
    enqueueInboundEventLocked(focusEntry);
}

void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) {
    sp<InputChannel> channel = getInputChannelLocked(entry->connectionToken);
    if (channel == nullptr) {
        return; // Window has gone away
    }
    InputTarget target;
    target.inputChannel = channel;
    target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
    entry->dispatchInProgress = true;

    dispatchEventLocked(currentTime, entry, {target});
}

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
                                        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Preprocessing.
@@ -1254,6 +1283,7 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) {
            displayId = motionEntry.displayId;
            break;
        }
        case EventEntry::Type::FOCUS:
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type));
@@ -1993,6 +2023,10 @@ std::string InputDispatcher::getApplicationWindowLabel(
}

void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
    if (eventEntry.type == EventEntry::Type::FOCUS) {
        // Focus events are passed to apps, but do not represent user activity.
        return;
    }
    int32_t displayId = getTargetDisplayId(eventEntry);
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
@@ -2027,6 +2061,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
            eventType = USER_ACTIVITY_EVENT_BUTTON;
            break;
        }
        case EventEntry::Type::FOCUS:
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            LOG_ALWAYS_FATAL("%s events are not user activity",
@@ -2224,6 +2259,9 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio

            break;
        }
        case EventEntry::Type::FOCUS: {
            break;
        }
        case EventEntry::Type::CONFIGURATION_CHANGED:
        case EventEntry::Type::DEVICE_RESET: {
            LOG_ALWAYS_FATAL("%s events should not go to apps",
@@ -2359,6 +2397,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                reportTouchEventForStatistics(*motionEntry);
                break;
            }
            case EventEntry::Type::FOCUS: {
                FocusEntry* focusEntry = static_cast<FocusEntry*>(eventEntry);
                status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq,
                                                                      focusEntry->hasFocus,
                                                                      mInTouchMode);
                break;
            }

            case EventEntry::Type::CONFIGURATION_CHANGED:
            case EventEntry::Type::DEVICE_RESET: {
                LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events",
@@ -2598,6 +2644,10 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
                                                     *cancelationEventEntry));
                    break;
                }
                case EventEntry::Type::FOCUS: {
                    LOG_ALWAYS_FATAL("Canceling focus events is not supported");
                    break;
                }
                case EventEntry::Type::CONFIGURATION_CHANGED:
                case EventEntry::Type::DEVICE_RESET: {
                    LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue",
@@ -3394,6 +3444,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                                               "focus left window");
                    synthesizeCancelationEventsForInputChannelLocked(focusedInputChannel, options);
                    enqueueFocusEventLocked(*oldFocusedWindowHandle, false /*hasFocus*/);
                }
                mFocusedWindowHandlesByDisplay.erase(displayId);
            }
@@ -3403,6 +3454,7 @@ void InputDispatcher::setInputWindows(const std::vector<sp<InputWindowHandle>>&
                          newFocusedWindowHandle->getName().c_str(), displayId);
                }
                mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
                enqueueFocusEventLocked(*newFocusedWindowHandle, true /*hasFocus*/);
            }

            if (mFocusedDisplayId == displayId) {
+4 −0
Original line number Diff line number Diff line
@@ -157,6 +157,9 @@ private:
    // Cleans up input state when dropping an inbound event.
    void dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) REQUIRES(mLock);

    // Enqueues a focus event.
    void enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) REQUIRES(mLock);

    // Adds an event to a queue of recent events for debugging purposes.
    void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock);

@@ -299,6 +302,7 @@ private:
                           nsecs_t* nextWakeupTime) REQUIRES(mLock);
    bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason,
                              nsecs_t* nextWakeupTime) REQUIRES(mLock);
    void dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) REQUIRES(mLock);
    void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
                             const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);

Loading