Add some tests for native input.

Test some important scenarios for input being driven by
SurfaceControl rather than the WindowManager.

Test: EndToEndNativeInputTest
Bug: 80101428
Bug: 113136004
Bug: 111440400
Change-Id: I46b302774a19c43d12680a8b7e2bb553dfcf4175
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 7ecadf8..a6295e0 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -16,6 +16,7 @@
         "BufferItemConsumer_test.cpp",
         "BufferQueue_test.cpp",
         "CpuConsumer_test.cpp",
+        "EndToEndNativeInputTest.cpp",
         "FillBuffer.cpp",
         "GLTest.cpp",
         "IGraphicBufferProducer_test.cpp",
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
new file mode 100644
index 0000000..2f165c4
--- /dev/null
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <poll.h>
+
+#include <memory>
+
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SurfaceControl.h>
+
+#include <input/InputWindow.h>
+#include <input/IInputFlinger.h>
+#include <input/InputTransport.h>
+#include <input/Input.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+
+namespace android {
+namespace test {
+
+sp<IInputFlinger> getInputFlinger() {
+   sp<IBinder> input(defaultServiceManager()->getService(
+            String16("inputflinger")));
+    if (input == nullptr) {
+        ALOGE("Failed to link to input service");
+    } else { ALOGE("Linked to input"); }
+    return interface_cast<IInputFlinger>(input);
+}
+
+// We use the top 10 layers as a way to haphazardly place ourselves above anything else.
+static const int LAYER_BASE = INT32_MAX - 10;
+
+class InputSurface {
+public:
+    InputSurface(const sp<SurfaceComposerClient>& scc, int width, int height) {
+        mSurfaceControl = scc->createSurface(String8("Test Surface"),
+                width, height, PIXEL_FORMAT_RGBA_8888,
+                ISurfaceComposerClient::eFXSurfaceColor);
+
+        InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
+        mServerChannel->setToken(new BBinder());
+
+        mInputFlinger = getInputFlinger();
+        mInputFlinger->registerInputChannel(mServerChannel);
+
+        populateInputInfo(width, height);
+
+        mInputConsumer = new InputConsumer(mClientChannel);
+    }
+
+    InputEvent* consumeEvent() {
+        waitForEventAvailable();
+
+        InputEvent *ev;
+        uint32_t seqId;
+        status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
+        if (consumed != OK) {
+            return nullptr;
+        }
+        mInputConsumer->sendFinishedSignal(seqId, true);
+        return ev;
+    }
+
+    void expectTap(int x, int y) {
+        InputEvent* ev = consumeEvent();
+        EXPECT_TRUE(ev != nullptr);
+        EXPECT_TRUE(ev->getType() == AINPUT_EVENT_TYPE_MOTION);
+        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);
+        mev = static_cast<MotionEvent*>(ev);
+        EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
+    }
+
+    ~InputSurface() {
+        mInputFlinger->unregisterInputChannel(mServerChannel);
+    }
+
+    void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
+                    const sp<SurfaceControl>&)> transactionBody) {
+        SurfaceComposerClient::Transaction t;
+        transactionBody(t, mSurfaceControl);
+        t.apply(true);
+    }
+
+    void showAt(int x, int y) {
+        SurfaceComposerClient::Transaction t;
+        t.show(mSurfaceControl);
+        t.setInputWindowInfo(mSurfaceControl, mInputInfo);
+        t.setLayer(mSurfaceControl, LAYER_BASE);
+        t.setPosition(mSurfaceControl, x, y);
+        t.setCrop_legacy(mSurfaceControl, Rect(0, 0, 100, 100));
+        t.setAlpha(mSurfaceControl, 1);
+        t.apply(true);
+    }
+
+private:
+    void waitForEventAvailable() {
+        struct pollfd fd;
+
+        fd.fd = mClientChannel->getFd();
+        fd.events = POLLIN;
+        poll(&fd, 1, 3000);
+    }
+
+    void populateInputInfo(int width, int height) {
+        mInputInfo.inputChannel = mServerChannel;
+        mInputInfo.name = "Test info";
+        mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
+        mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION;
+        mInputInfo.dispatchingTimeout = 100000;
+        mInputInfo.scaleFactor = 1.0;
+        mInputInfo.canReceiveKeys = true;
+        mInputInfo.hasFocus = 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.inputFeatures = 0;
+        mInputInfo.displayId = 0;
+    }
+public:
+    sp<SurfaceControl> mSurfaceControl;
+    sp<InputChannel> mServerChannel, mClientChannel;
+    sp<IInputFlinger> mInputFlinger;
+
+    InputWindowInfo mInputInfo;
+
+    PreallocatedInputEventFactory mInputEventFactory;
+    InputConsumer* mInputConsumer;
+};
+
+class InputSurfacesTest : public ::testing::Test {
+public:
+    InputSurfacesTest() {
+        ProcessState::self()->startThreadPool();
+    }
+
+    void SetUp() {
+        mComposerClient = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+    }
+
+    void TearDown() {
+        mComposerClient->dispose();
+    }
+
+    std::unique_ptr<InputSurface> makeSurface(int width, int height) {
+        return std::make_unique<InputSurface>(mComposerClient, width, height);
+    }
+
+    sp<SurfaceComposerClient> mComposerClient;
+};
+
+void injectTap(int x, int y) {
+    char *buf1, *buf2;
+    asprintf(&buf1, "%d", x);
+    asprintf(&buf2, "%d", y);
+    if (fork() == 0) {
+        execlp("input", "input", "tap", buf1, buf2, NULL);
+    }
+}
+
+TEST_F(InputSurfacesTest, can_receive_input) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(100, 100);
+
+    injectTap(101, 101);
+
+    EXPECT_TRUE(surface->consumeEvent() != nullptr);
+}
+
+TEST_F(InputSurfacesTest, input_respects_positioning) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(100, 100);
+
+    std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
+    surface2->showAt(200, 200);
+
+    injectTap(201, 201);
+    surface2->expectTap(1, 1);
+
+    injectTap(101, 101);
+    surface->expectTap(1, 1);
+
+    surface2->doTransaction([](auto &t, auto &sc) {
+         t.setPosition(sc, 100, 100);
+    });
+    surface->doTransaction([](auto &t, auto &sc) {
+         t.setPosition(sc, 200, 200);
+    });
+
+    injectTap(101, 101);
+    surface2->expectTap(1, 1);
+
+    injectTap(201, 201);
+    surface->expectTap(1, 1);
+}
+
+TEST_F(InputSurfacesTest, input_respects_layering) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
+
+    surface->showAt(10, 10);
+    surface2->showAt(10, 10);
+
+    surface->doTransaction([](auto &t, auto &sc) {
+         t.setLayer(sc, LAYER_BASE + 1);
+    });
+
+    injectTap(11, 11);
+    surface->expectTap(1, 1);
+
+    surface2->doTransaction([](auto &t, auto &sc) {
+         t.setLayer(sc, LAYER_BASE + 1);
+    });
+
+    injectTap(11, 11);
+    surface2->expectTap(1, 1);
+
+    surface2->doTransaction([](auto &t, auto &sc) {
+         t.hide(sc);
+    });
+
+    injectTap(11, 11);
+    surface->expectTap(1, 1);
+}
+
+}
+}
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index 47a2c0c..477e54e 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -40,6 +40,20 @@
         }
         remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply);
     }
+
+    virtual void registerInputChannel(const sp<InputChannel>& channel) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+        channel->write(data);
+        remote()->transact(BnInputFlinger::REGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply);
+    }
+
+    virtual void unregisterInputChannel(const sp<InputChannel>& channel) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+        channel->write(data);
+        remote()->transact(BnInputFlinger::UNREGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
@@ -61,6 +75,20 @@
         setInputWindows(handles);
         break;
     }
+    case REGISTER_INPUT_CHANNEL_TRANSACTION: {
+        CHECK_INTERFACE(IInputFlinger, data, reply);
+        sp<InputChannel> channel = new InputChannel();
+        channel->read(data);
+        registerInputChannel(channel);
+        break;
+    }
+    case UNREGISTER_INPUT_CHANNEL_TRANSACTION: {
+        CHECK_INTERFACE(IInputFlinger, data, reply);
+        sp<InputChannel> channel = new InputChannel();
+        channel->read(data);
+        unregisterInputChannel(channel);
+        break;
+    }
     default:
         return BBinder::onTransact(code, data, reply, flags);
     }