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

Commit 4c0e4319 authored by Linus Tufvesson's avatar Linus Tufvesson
Browse files

Allow windowhandles with NO_INPUT_CHANNEL - DO NOT MERGE

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 InputSurfacesTest
Change-Id: Iacfc952139311363b914b1d6bffc2b4190133d02
(cherry picked from commit a1858820)
parent 04caf0c7
Loading
Loading
Loading
Loading
+58 −32
Original line number Diff line number Diff line
@@ -69,16 +69,39 @@ 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.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL;
        } 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.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
        mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION;
        mInputInfo.focusable = true;
        mInputInfo.hasWallpaper = false;
        mInputInfo.paused = false;
        // TODO: Fill in from SF?
        mInputInfo.ownerPid = 11111;
        mInputInfo.ownerUid = 11111;
        mInputInfo.displayId = 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,
@@ -107,6 +130,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"), 0 /* bufHeight */,
                                   0 /* bufWidth */, 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 =
@@ -193,8 +226,10 @@ public:
    }

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

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

    void populateInputInfo(int width, int height) {
        mInputInfo.token = mClientChannel->getConnectionToken();
        mInputInfo.name = "Test info";
        mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
        mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION;
        mInputInfo.dispatchingTimeout = 5s;
        mInputInfo.globalScaleFactor = 1.0;
        mInputInfo.focusable = true;
        mInputInfo.hasWallpaper = false;
        mInputInfo.paused = false;

        mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));

        // TODO: Fill in from SF?
        mInputInfo.ownerPid = 11111;
        mInputInfo.ownerUid = 11111;
        mInputInfo.displayId = 0;

        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;
@@ -818,4 +827,21 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) {
    surface->expectTap(1, 1);
}

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);
}

} // namespace android::test
+3 −2
Original line number Diff line number Diff line
@@ -2151,7 +2151,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
        layerInfo->set_owner_uid(mOwnerUid);
    }

    if (traceFlags & SurfaceTracing::TRACE_INPUT) {
    if (traceFlags & SurfaceTracing::TRACE_INPUT && needsInputInfo()) {
        InputWindowInfo info;
        if (useDrawing) {
            info = fillInputInfo({nullptr});
@@ -2399,7 +2399,8 @@ sp<Layer> Layer::getClonedRoot() {
}

bool Layer::hasInputInfo() const {
    return mDrawingState.inputInfo.token != nullptr;
    return mDrawingState.inputInfo.token != nullptr ||
            mDrawingState.inputInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
}

bool Layer::canReceiveInput() const {