AIDL-ize InputManager IInputFlinger interface.
Use AIDL interface to define the IInputFlinger interface and replace
the manual interface.
Bug:155425003
Test: atest libgui_test, atest libinput_test.
Change-Id: Ibad036b8ceb3a3f5c6d58f8de4ea8c79379d29b5
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index f2a0014..c5f60ad 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -93,16 +93,15 @@
class BinderWindowHandle : public InputWindowHandle {
public:
- BinderWindowHandle(const InputWindowInfo& info) {
- mInfo = info;
- }
+ BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; }
bool updateInfo() override {
return true;
}
};
-void InputManager::setInputWindows(const std::vector<InputWindowInfo>& infos,
+binder::Status InputManager::setInputWindows(
+ const std::vector<InputWindowInfo>& infos,
const sp<ISetInputWindowsListener>& setInputWindowsListener) {
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> handlesPerDisplay;
@@ -116,22 +115,38 @@
if (setInputWindowsListener) {
setInputWindowsListener->onSetInputWindowsFinished();
}
+ return binder::Status::ok();
}
// Used by tests only.
-void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
+binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) {
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid != AID_SHELL && uid != AID_ROOT) {
ALOGE("Invalid attempt to register input channel over IPC"
"from non shell/root entity (PID: %d)", ipc->getCallingPid());
- return;
+ return binder::Status::ok();
}
+ android::base::unique_fd newFd(::dup(info.mFd));
+ sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
mDispatcher->registerInputChannel(channel);
+ return binder::Status::ok();
}
-void InputManager::unregisterInputChannel(const sp<InputChannel>& channel) {
+binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) {
+ android::base::unique_fd newFd(::dup(info.mFd));
+ sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
mDispatcher->unregisterInputChannel(channel);
+ return binder::Status::ok();
+}
+
+status_t InputManager::dump(int fd, const Vector<String16>& args) {
+ std::string dump;
+
+ dump += " InputFlinger dump\n";
+
+ ::write(fd, dump.c_str(), dump.size());
+ return NO_ERROR;
}
} // namespace android
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 41d9478..4993b54 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -26,18 +26,23 @@
#include <InputDispatcherInterface.h>
#include <InputDispatcherPolicyInterface.h>
-#include <input/ISetInputWindowsListener.h>
+#include <android/os/ISetInputWindowsListener.h>
#include <input/Input.h>
#include <input/InputTransport.h>
-#include <input/IInputFlinger.h>
+#include <android/os/BnInputFlinger.h>
+#include <android/os/IInputFlinger.h>
#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+using android::os::BnInputFlinger;
+using android::os::ISetInputWindowsListener;
namespace android {
class InputChannel;
+class InputDispatcherThread;
/*
* The input manager is the core of the system event processing.
@@ -98,11 +103,13 @@
sp<InputClassifierInterface> getClassifier() override;
sp<InputDispatcherInterface> getDispatcher() override;
- void setInputWindows(const std::vector<InputWindowInfo>& handles,
- const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
+ status_t dump(int fd, const Vector<String16>& args) override;
+ binder::Status setInputWindows(
+ const std::vector<InputWindowInfo>& handles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
- void registerInputChannel(const sp<InputChannel>& channel) override;
- void unregisterInputChannel(const sp<InputChannel>& channel) override;
+ binder::Status registerInputChannel(const InputChannelInfo& info) override;
+ binder::Status unregisterInputChannel(const InputChannelInfo& info) override;
private:
sp<InputReaderInterface> mReader;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 9b002f4..f25131c 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -18,15 +18,14 @@
#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
#include <InputListener.h>
-#include <input/ISetInputWindowsListener.h>
+#include <android/os/ISetInputWindowsListener.h>
+#include <input/InputApplication.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
#include <unordered_map>
namespace android {
-class InputApplicationHandle;
-class InputChannel;
-class InputWindowHandle;
-
/*
* Constants used to report the outcome of input event injection.
*/
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 21255dd..c886bee 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -21,11 +21,11 @@
#include <binder/IBinder.h>
#include <input/Input.h>
+#include <input/InputApplication.h>
#include <utils/RefBase.h>
namespace android {
-class InputApplicationHandle;
/*
* Input dispatcher policy interface.
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index b56f356..2643c22 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -59,7 +59,8 @@
shared_libs: [
"libbinder",
"libinputflingerhost",
- "libutils"
+ "libutils",
+ "libinput"
],
static_libs: [
"libarect",
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 973b4f9..9364a2a 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -22,13 +22,17 @@
#include "InputHost.h"
+#include <android/os/BnInputFlinger.h>
+#include <android/os/ISetInputWindowsListener.h>
+#include <binder/Binder.h>
#include <cutils/compiler.h>
-#include <input/IInputFlinger.h>
-#include <input/ISetInputWindowsListener.h>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
#include <utils/StrongPointer.h>
+using android::os::BnInputFlinger;
+using android::os::ISetInputWindowsListener;
+
namespace android {
class InputFlinger : public BnInputFlinger {
@@ -40,10 +44,12 @@
InputFlinger() ANDROID_API;
virtual status_t dump(int fd, const Vector<String16>& args);
- void setInputWindows(const std::vector<InputWindowInfo>&,
- const sp<ISetInputWindowsListener>&) {}
- void registerInputChannel(const sp<InputChannel>&) {}
- void unregisterInputChannel(const sp<InputChannel>&) {}
+ binder::Status setInputWindows(const std::vector<InputWindowInfo>&,
+ const sp<ISetInputWindowsListener>&) {
+ return binder::Status::ok();
+ }
+ binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); }
+ binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); }
private:
virtual ~InputFlinger();
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a0d2f4f..eae0963 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -35,7 +35,14 @@
"InputClassifierConverter_test.cpp",
"InputDispatcher_test.cpp",
"InputReader_test.cpp",
+ "InputFlingerService_test.cpp",
"UinputDevice.cpp",
+ "IInputFlingerQuery.aidl"
],
+ aidl: {
+ include_dirs: [
+ "frameworks/native/libs/input",
+ ],
+ },
require_root: true,
}
diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl
new file mode 100644
index 0000000..1edc089
--- /dev/null
+++ b/services/inputflinger/tests/IInputFlingerQuery.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2020, 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.
+ */
+
+import android.InputChannelInfo;
+import android.InputWindowInfo;
+import android.os.ISetInputWindowsListener;
+
+/** @hide */
+interface IInputFlingerQuery
+{
+ /* Test interfaces */
+ void getInputWindows(out InputWindowInfo[] inputHandles);
+ void getInputChannels(out InputChannelInfo[] infos);
+}
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
new file mode 100644
index 0000000..fd3f562
--- /dev/null
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2020 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 <BnInputFlingerQuery.h>
+#include <IInputFlingerQuery.h>
+
+#include <android/os/BnInputFlinger.h>
+#include <android/os/BnSetInputWindowsListener.h>
+#include <android/os/IInputFlinger.h>
+#include <android/os/ISetInputWindowsListener.h>
+
+#include <binder/Binder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+
+#include <input/Input.h>
+#include <input/InputTransport.h>
+#include <input/InputWindow.h>
+
+#include <gtest/gtest.h>
+#include <inttypes.h>
+#include <linux/uinput.h>
+#include <log/log.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <chrono>
+#include <thread>
+#include <unordered_map>
+
+#define TAG "InputFlingerServiceTest"
+
+using android::os::BnInputFlinger;
+using android::os::BnSetInputWindowsListener;
+using android::os::IInputFlinger;
+using android::os::ISetInputWindowsListener;
+
+using std::chrono_literals::operator""ms;
+using std::chrono_literals::operator""s;
+
+namespace android {
+
+static const sp<IBinder> TestInfoToken = new BBinder();
+static constexpr int32_t TestInfoId = 1;
+static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo";
+static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD;
+static constexpr int32_t TestInfoLayoutParamsType = 39;
+static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms;
+static constexpr int32_t TestInfoFrameLeft = 93;
+static constexpr int32_t TestInfoFrameTop = 34;
+static constexpr int32_t TestInfoFrameRight = 16;
+static constexpr int32_t TestInfoFrameBottom = 19;
+static constexpr int32_t TestInfoSurfaceInset = 17;
+static constexpr float TestInfoGlobalScaleFactor = 0.3;
+static constexpr float TestInfoWindowXScale = 0.4;
+static constexpr float TestInfoWindowYScale = 0.5;
+static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */,
+ 450 /* bottom */};
+static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect);
+static constexpr bool TestInfoVisible = false;
+static constexpr bool TestInfoCanReceiveKeys = false;
+static constexpr bool TestInfoTrustedOverlay = true;
+static constexpr bool TestInfoHasFocus = false;
+static constexpr bool TestInfoHasWallpaper = false;
+static constexpr bool TestInfoPaused = false;
+static constexpr int32_t TestInfoOwnerPid = 19;
+static constexpr int32_t TestInfoOwnerUid = 24;
+static constexpr int32_t TestInfoInputFeatures = 29;
+static constexpr int32_t TestInfoDisplayId = 34;
+static constexpr int32_t TestInfoPortalToDisplayId = 2;
+static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true;
+static const sp<IBinder> TestInfoTouchableRegionCropHandle = new BBinder();
+
+static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo";
+static const sp<IBinder> TestAppInfoToken = new BBinder();
+static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms;
+
+static const String16 kTestServiceName = String16("InputFlingerService");
+static const String16 kQueryServiceName = String16("InputFlingerQueryService");
+
+struct SetInputWindowsListener;
+// --- InputFlingerServiceTest ---
+class InputFlingerServiceTest : public testing::Test {
+public:
+ void SetUp() override;
+ void TearDown() override;
+
+protected:
+ void InitializeInputFlinger();
+ void setInputWindowsByInfos(std::vector<InputWindowInfo>& infos);
+
+ void setInputWindowsFinished();
+ void verifyInputWindowInfo(const InputWindowInfo& info) const;
+ InputWindowInfo& getInfo() const { return const_cast<InputWindowInfo&>(mInfo); }
+
+ sp<IInputFlinger> mService;
+ sp<IInputFlingerQuery> mQuery;
+
+private:
+ sp<SetInputWindowsListener> mSetInputWindowsListener;
+ sp<InputChannel> mServerChannel, mClientChannel;
+ InputWindowInfo mInfo;
+ std::mutex mLock;
+ std::condition_variable mSetInputWindowsFinishedCondition;
+};
+
+struct SetInputWindowsListener : BnSetInputWindowsListener {
+ explicit SetInputWindowsListener(std::function<void()> cbFunc) : mCbFunc(cbFunc) {}
+
+ binder::Status onSetInputWindowsFinished() override;
+
+ std::function<void()> mCbFunc;
+};
+
+class TestInputManager : public BnInputFlinger {
+protected:
+ virtual ~TestInputManager(){};
+
+public:
+ TestInputManager(){};
+ void checkFdFlags(const android::base::unique_fd& fd);
+
+ binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
+ binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos);
+
+ status_t dump(int fd, const Vector<String16>& args) override;
+
+ binder::Status setInputWindows(
+ const std::vector<InputWindowInfo>& handles,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
+
+ binder::Status registerInputChannel(const InputChannelInfo& channel) override;
+ binder::Status unregisterInputChannel(const InputChannelInfo& channel) override;
+
+private:
+ mutable Mutex mLock;
+ std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
+ std::vector<sp<InputChannel>> mInputChannels;
+};
+
+class TestInputQuery : public BnInputFlingerQuery {
+public:
+ TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){};
+ binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
+ binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override;
+
+private:
+ sp<android::TestInputManager> mManager;
+};
+
+binder::Status TestInputQuery::getInputWindows(
+ std::vector<::android::InputWindowInfo>* inputHandles) {
+ return mManager->getInputWindows(inputHandles);
+}
+
+binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
+ return mManager->getInputChannels(infos);
+}
+
+binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
+ if (mCbFunc != nullptr) {
+ mCbFunc();
+ }
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::setInputWindows(
+ const std::vector<InputWindowInfo>& infos,
+ const sp<ISetInputWindowsListener>& setInputWindowsListener) {
+ AutoMutex _l(mLock);
+
+ for (const auto& info : infos) {
+ mHandlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
+ mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info));
+ }
+ if (setInputWindowsListener) {
+ setInputWindowsListener->onSetInputWindowsFinished();
+ }
+ return binder::Status::ok();
+}
+
+void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) {
+ const int result = fcntl(fd, F_GETFL);
+ EXPECT_NE(result, -1);
+ EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
+}
+
+binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) {
+ AutoMutex _l(mLock);
+ // check Fd flags
+ checkFdFlags(info.mFd);
+
+ android::base::unique_fd newFd(::dup(info.mFd));
+ sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
+ mInputChannels.push_back(channel);
+
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) {
+ AutoMutex _l(mLock);
+ // check Fd flags
+ checkFdFlags(info.mFd);
+ android::base::unique_fd newFd(::dup(info.mFd));
+ sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
+
+ auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
+ [&](sp<InputChannel>& it) { return *it == *channel; });
+ if (it != mInputChannels.end()) {
+ mInputChannels.erase(it);
+ }
+
+ return binder::Status::ok();
+}
+
+status_t TestInputManager::dump(int fd, const Vector<String16>& args) {
+ std::string dump;
+
+ dump += " InputFlinger dump\n";
+
+ ::write(fd, dump.c_str(), dump.size());
+ return NO_ERROR;
+}
+
+binder::Status TestInputManager::getInputWindows(
+ std::vector<::android::InputWindowInfo>* inputInfos) {
+ for (auto& [displayId, inputHandles] : mHandlesPerDisplay) {
+ for (auto& inputHandle : inputHandles) {
+ inputInfos->push_back(*inputHandle->getInfo());
+ }
+ }
+ return binder::Status::ok();
+}
+
+binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) {
+ infos->clear();
+ for (auto& channel : mInputChannels) {
+ auto chanDup = channel->dup();
+ infos->push_back(std::move(chanDup->getInfo()));
+ }
+ return binder::Status::ok();
+}
+
+void InputFlingerServiceTest::SetUp() {
+ mSetInputWindowsListener = new SetInputWindowsListener([&]() {
+ std::unique_lock<std::mutex> lock(mLock);
+ mSetInputWindowsFinishedCondition.notify_all();
+ });
+ InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel);
+
+ mInfo.token = TestInfoToken;
+ mInfo.id = TestInfoId;
+ mInfo.name = TestInfoName;
+ mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags;
+ mInfo.layoutParamsType = TestInfoLayoutParamsType;
+ mInfo.dispatchingTimeout = TestInfoDispatchingTimeout;
+ mInfo.frameLeft = TestInfoFrameLeft;
+ mInfo.frameTop = TestInfoFrameTop;
+ mInfo.frameRight = TestInfoFrameRight;
+ mInfo.frameBottom = TestInfoFrameBottom;
+ mInfo.surfaceInset = TestInfoSurfaceInset;
+ mInfo.globalScaleFactor = TestInfoGlobalScaleFactor;
+ mInfo.windowXScale = TestInfoWindowXScale;
+ mInfo.windowYScale = TestInfoWindowYScale;
+ mInfo.touchableRegion = TestInfoTouchableRegion;
+ mInfo.visible = TestInfoVisible;
+ mInfo.canReceiveKeys = TestInfoCanReceiveKeys;
+ mInfo.trustedOverlay = TestInfoTrustedOverlay;
+ mInfo.hasFocus = TestInfoHasFocus;
+ mInfo.hasWallpaper = TestInfoHasWallpaper;
+ mInfo.paused = TestInfoPaused;
+ mInfo.ownerPid = TestInfoOwnerPid;
+ mInfo.ownerUid = TestInfoOwnerUid;
+ mInfo.inputFeatures = TestInfoInputFeatures;
+ mInfo.displayId = TestInfoDisplayId;
+ mInfo.portalToDisplayId = TestInfoPortalToDisplayId;
+ mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop;
+ mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle;
+
+ mInfo.applicationInfo.name = TestAppInfoName;
+ mInfo.applicationInfo.token = TestAppInfoToken;
+ mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout;
+
+ InitializeInputFlinger();
+}
+
+void InputFlingerServiceTest::TearDown() {}
+
+void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
+ EXPECT_EQ(mInfo, info);
+}
+
+void InputFlingerServiceTest::InitializeInputFlinger() {
+ sp<IBinder> input(defaultServiceManager()->waitForService(kTestServiceName));
+ ASSERT_TRUE(input != nullptr);
+ mService = interface_cast<IInputFlinger>(input);
+
+ input = defaultServiceManager()->waitForService(kQueryServiceName);
+ ASSERT_TRUE(input != nullptr);
+ mQuery = interface_cast<IInputFlingerQuery>(input);
+}
+
+void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) {
+ std::unique_lock<std::mutex> lock(mLock);
+ mService->setInputWindows(infos, mSetInputWindowsListener);
+ // Verify listener call
+ EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout);
+ // Verify input windows from service
+ std::vector<::android::InputWindowInfo> inputHandles;
+ mQuery->getInputWindows(&inputHandles);
+ for (auto& inputInfo : inputHandles) {
+ verifyInputWindowInfo(inputInfo);
+ }
+}
+
+/**
+ * Test InputFlinger service interface SetInputWindows
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) {
+ std::vector<InputWindowInfo> infos = {getInfo()};
+ setInputWindowsByInfos(infos);
+}
+
+/**
+ * Test InputFlinger service interface registerInputChannel
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
+ sp<InputChannel> serverChannel, clientChannel;
+
+ InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
+ mService->registerInputChannel(serverChannel->getInfo());
+
+ std::vector<::android::InputChannelInfo> infos(2);
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 1UL);
+
+ auto& info = infos[0];
+ android::base::unique_fd newFd(::dup(info.mFd));
+ sp<InputChannel> channel = InputChannel::create(info.mName, std::move(newFd), info.mToken);
+ EXPECT_EQ(*channel, *serverChannel);
+
+ mService->unregisterInputChannel(serverChannel->getInfo());
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 0UL);
+}
+
+/**
+ * Test InputFlinger service interface registerInputChannel with invalid cases
+ */
+TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
+ sp<InputChannel> serverChannel, clientChannel;
+ InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
+
+ std::vector<::android::InputChannelInfo> infos(2);
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 0UL);
+
+ mService->registerInputChannel(InputChannelInfo());
+ mService->unregisterInputChannel(clientChannel->getInfo());
+
+ mService->registerInputChannel(serverChannel->getInfo());
+ mService->registerInputChannel(clientChannel->getInfo());
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 2UL);
+
+ mService->unregisterInputChannel(clientChannel->getInfo());
+ mService->unregisterInputChannel(serverChannel->getInfo());
+ mQuery->getInputChannels(&infos);
+ EXPECT_EQ(infos.size(), 0UL);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+ pid_t forkPid = fork();
+
+ if (forkPid == 0) {
+ // Server process
+ android::sp<android::TestInputManager> manager = new android::TestInputManager();
+ android::sp<android::TestInputQuery> query = new android::TestInputQuery(manager);
+
+ android::defaultServiceManager()->addService(android::kTestServiceName, manager,
+ false /*allowIsolated*/);
+ android::defaultServiceManager()->addService(android::kQueryServiceName, query,
+ false /*allowIsolated*/);
+ android::ProcessState::self()->startThreadPool();
+ android::IPCThreadState::self()->joinThreadPool();
+ } else {
+ android::ProcessState::self()->startThreadPool();
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+ }
+ return 0;
+}