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

Commit a1858820 authored by Linus Tufvesson's avatar Linus Tufvesson
Browse files

Allow windowhandles with NO_INPUT_CHANNEL

This allows container surfaces to be considered visible in
InputDispatcher and prevent touches from passing through them. In
particular this is used by ActivityRecordInputSink to block touches that
would otherwise pass through the area available to the activity.

Bug: 194480991
Bug: 222292477
Test: Manually tested that blocking still works
Test: atest android.server.wm.WindowUntrustedTouchTest
Test: atest InputSurfacesTest
Change-Id: Icb419d6c61d63eeeda4b6a9ad725cd4829fd6fc8
parent 0af0bba3
Loading
Loading
Loading
Loading
+49 −21
Original line number Diff line number Diff line
@@ -76,16 +76,30 @@ static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;

class InputSurface {
public:
    InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
    InputSurface(const sp<SurfaceControl> &sc, int width, int height, bool noInputChannel = false) {
        mSurfaceControl = sc;

        mInputFlinger = getInputFlinger();
        if (noInputChannel) {
            mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true);
        } else {
            mClientChannel = std::make_shared<InputChannel>();
            mInputFlinger->createInputChannel("testchannels", mClientChannel.get());
            mInputInfo.token = mClientChannel->getConnectionToken();
            mInputConsumer = new InputConsumer(mClientChannel);
        }

        populateInputInfo(width, height);
        mInputInfo.name = "Test info";
        mInputInfo.dispatchingTimeout = 5s;
        mInputInfo.globalScaleFactor = 1.0;
        mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));

        mInputConsumer = new InputConsumer(mClientChannel);
        InputApplicationInfo aInfo;
        aInfo.token = new BBinder();
        aInfo.name = "Test app info";
        aInfo.dispatchingTimeoutMillis =
                std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
        mInputInfo.applicationInfo = aInfo;
    }

    static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc,
@@ -114,6 +128,16 @@ public:
        return std::make_unique<InputSurface>(surfaceControl, width, height);
    }

    static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel(
            const sp<SurfaceComposerClient> &scc, int width, int height) {
        sp<SurfaceControl> surfaceControl =
                scc->createSurface(String8("Test Container Surface"), 100 /* height */,
                                   100 /* width */, PIXEL_FORMAT_RGBA_8888,
                                   ISurfaceComposerClient::eFXSurfaceContainer);
        return std::make_unique<InputSurface>(surfaceControl, width, height,
                                              true /* noInputChannel */);
    }

    static std::unique_ptr<InputSurface> makeCursorInputSurface(
            const sp<SurfaceComposerClient> &scc, int width, int height) {
        sp<SurfaceControl> surfaceControl =
@@ -219,8 +243,10 @@ public:
    }

    virtual ~InputSurface() {
        if (mClientChannel) {
            mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken());
        }
    }

    virtual void doTransaction(
            std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)>
@@ -263,21 +289,6 @@ private:
        poll(&fd, 1, timeoutMs);
    }

    void populateInputInfo(int width, int height) {
        mInputInfo.token = mClientChannel->getConnectionToken();
        mInputInfo.name = "Test info";
        mInputInfo.dispatchingTimeout = 5s;
        mInputInfo.globalScaleFactor = 1.0;
        mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));

        InputApplicationInfo aInfo;
        aInfo.token = new BBinder();
        aInfo.name = "Test app info";
        aInfo.dispatchingTimeoutMillis =
                std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();

        mInputInfo.applicationInfo = aInfo;
    }
public:
    sp<SurfaceControl> mSurfaceControl;
    std::shared_ptr<InputChannel> mClientChannel;
@@ -1085,6 +1096,23 @@ TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) {
    EXPECT_EQ(containerSurface->consumeEvent(100), nullptr);
}

TEST_F(InputSurfacesTest, child_container_with_no_input_channel_blocks_parent) {
    std::unique_ptr<InputSurface> parent = makeSurface(100, 100);

    parent->showAt(100, 100);
    injectTap(101, 101);
    parent->expectTap(1, 1);

    std::unique_ptr<InputSurface> childContainerSurface =
            InputSurface::makeContainerInputSurfaceNoInputChannel(mComposerClient, 100, 100);
    childContainerSurface->showAt(0, 0);
    childContainerSurface->doTransaction(
            [&](auto &t, auto &sc) { t.reparent(sc, parent->mSurfaceControl); });
    injectTap(101, 101);

    EXPECT_EQ(parent->consumeEvent(100), nullptr);
}

class MultiDisplayTests : public InputSurfacesTest {
public:
    MultiDisplayTests() : InputSurfacesTest() { ProcessState::self()->startThreadPool(); }
+2 −1
Original line number Diff line number Diff line
@@ -2392,7 +2392,8 @@ sp<Layer> Layer::getClonedRoot() {
}

bool Layer::hasInputInfo() const {
    return mDrawingState.inputInfo.token != nullptr;
    return mDrawingState.inputInfo.token != nullptr ||
            mDrawingState.inputInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
}

bool Layer::canReceiveInput() const {