Second reland "Let InputFlinger create the server InputChannel"
Bug: 167947395
Bug: 169173706
Test: atest NexusLauncherTests:com.android.launcher3.ui.TaplTestsLauncher3
Change-Id: I9cbe8ce92d006abfe9246f88844730951caf940b
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 8e00969..ad0a14e 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -246,6 +246,8 @@
/* Return a new object that has a duplicate of this channel's fd. */
std::unique_ptr<InputChannel> dup() const;
+ void copyTo(InputChannel& outChannel) const;
+
status_t readFromParcel(const android::Parcel* parcel) override;
status_t writeToParcel(android::Parcel* parcel) const override;
@@ -277,6 +279,8 @@
}
private:
+ base::unique_fd dupFd() const;
+
std::string mName;
android::base::unique_fd mFd;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 4d306e7..ac79583 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -68,12 +68,10 @@
public:
InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
mSurfaceControl = sc;
- std::unique_ptr<InputChannel> clientChannel;
- InputChannel::openInputChannelPair("testchannels", mServerChannel, clientChannel);
- mClientChannel = std::move(clientChannel);
mInputFlinger = getInputFlinger();
- mInputFlinger->registerInputChannel(*mServerChannel);
+ mClientChannel = std::make_shared<InputChannel>();
+ mInputFlinger->createInputChannel("testchannels", mClientChannel.get());
populateInputInfo(width, height);
@@ -155,7 +153,7 @@
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
}
- ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getConnectionToken()); }
+ ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); }
void doTransaction(std::function<void(SurfaceComposerClient::Transaction&,
const sp<SurfaceControl>&)> transactionBody) {
@@ -192,7 +190,7 @@
}
void populateInputInfo(int width, int height) {
- mInputInfo.token = mServerChannel->getConnectionToken();
+ mInputInfo.token = mClientChannel->getConnectionToken();
mInputInfo.name = "Test info";
mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION;
@@ -219,7 +217,6 @@
}
public:
sp<SurfaceControl> mSurfaceControl;
- std::unique_ptr<InputChannel> mServerChannel;
std::shared_ptr<InputChannel> mClientChannel;
sp<IInputFlinger> mInputFlinger;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 79e15c1..85df405 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -377,22 +377,16 @@
}
std::unique_ptr<InputChannel> InputChannel::dup() const {
- android::base::unique_fd newFd(::dup(getFd()));
- if (!newFd.ok()) {
- ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(),
- strerror(errno));
- const bool hitFdLimit = errno == EMFILE || errno == ENFILE;
- // If this process is out of file descriptors, then throwing that might end up exploding
- // on the other side of a binder call, which isn't really helpful.
- // Better to just crash here and hope that the FD leak is slow.
- // Other failures could be client errors, so we still propagate those back to the caller.
- LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s",
- getName().c_str());
- return nullptr;
- }
+ base::unique_fd newFd(dupFd());
return InputChannel::create(getName(), std::move(newFd), getConnectionToken());
}
+void InputChannel::copyTo(InputChannel& outChannel) const {
+ outChannel.mName = getName();
+ outChannel.mFd = dupFd();
+ outChannel.mToken = getConnectionToken();
+}
+
status_t InputChannel::writeToParcel(android::Parcel* parcel) const {
if (parcel == nullptr) {
ALOGE("%s: Null parcel", __func__);
@@ -415,6 +409,23 @@
return mToken;
}
+base::unique_fd InputChannel::dupFd() const {
+ android::base::unique_fd newFd(::dup(getFd()));
+ if (!newFd.ok()) {
+ ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(),
+ strerror(errno));
+ const bool hitFdLimit = errno == EMFILE || errno == ENFILE;
+ // If this process is out of file descriptors, then throwing that might end up exploding
+ // on the other side of a binder call, which isn't really helpful.
+ // Better to just crash here and hope that the FD leak is slow.
+ // Other failures could be client errors, so we still propagate those back to the caller.
+ LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s",
+ getName().c_str());
+ return {};
+ }
+ return newFd;
+}
+
// --- InputPublisher ---
InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {}
diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl
index 0cdf0bb..1771d19 100644
--- a/libs/input/android/os/IInputFlinger.aidl
+++ b/libs/input/android/os/IInputFlinger.aidl
@@ -30,8 +30,8 @@
// shouldn't be a concern.
oneway void setInputWindows(in InputWindowInfo[] inputHandles,
in @nullable ISetInputWindowsListener setInputWindowsListener);
- void registerInputChannel(in InputChannel channel);
- void unregisterInputChannel(in IBinder connectionToken);
+ InputChannel createInputChannel(in @utf8InCpp String name);
+ void removeInputChannel(in IBinder connectionToken);
/**
* Sets focus to the window identified by the token. This must be called
* after updating any input window handles.
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 8af9bcb..3d99589 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -31,6 +31,25 @@
namespace android {
+static int32_t exceptionCodeFromStatusT(status_t status) {
+ switch (status) {
+ case OK:
+ return binder::Status::EX_NONE;
+ case INVALID_OPERATION:
+ return binder::Status::EX_UNSUPPORTED_OPERATION;
+ case BAD_VALUE:
+ case BAD_TYPE:
+ case NAME_NOT_FOUND:
+ return binder::Status::EX_ILLEGAL_ARGUMENT;
+ case NO_INIT:
+ return binder::Status::EX_ILLEGAL_STATE;
+ case PERMISSION_DENIED:
+ return binder::Status::EX_SECURITY;
+ default:
+ return binder::Status::EX_TRANSACTION_FAILED;
+ }
+}
+
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
@@ -119,7 +138,7 @@
}
// Used by tests only.
-binder::Status InputManager::registerInputChannel(const InputChannel& channel) {
+binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) {
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid != AID_SHELL && uid != AID_ROOT) {
@@ -128,12 +147,17 @@
return binder::Status::ok();
}
- mDispatcher->registerInputChannel(channel.dup());
+ base::Result<std::unique_ptr<InputChannel>> channel = mDispatcher->createInputChannel(name);
+ if (!channel) {
+ return binder::Status::fromExceptionCode(exceptionCodeFromStatusT(channel.error().code()),
+ channel.error().message().c_str());
+ }
+ (*channel)->copyTo(*outChannel);
return binder::Status::ok();
}
-binder::Status InputManager::unregisterInputChannel(const sp<IBinder>& connectionToken) {
- mDispatcher->unregisterInputChannel(connectionToken);
+binder::Status InputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
+ mDispatcher->removeInputChannel(connectionToken);
return binder::Status::ok();
}
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 35d2d58..49bea13 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -108,8 +108,8 @@
const std::vector<InputWindowInfo>& handles,
const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
- binder::Status registerInputChannel(const InputChannel& channel) override;
- binder::Status unregisterInputChannel(const sp<IBinder>& connectionToken) override;
+ binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
+ binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
binder::Status setFocusedWindow(const FocusRequest&) override;
private:
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index b645d69..46bc055 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -129,17 +129,14 @@
protected:
explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher, const std::string name)
: mDispatcher(dispatcher) {
- std::unique_ptr<InputChannel> serverChannel, clientChannel;
- InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
- mServerChannel = std::move(serverChannel);
- mClientChannel = std::move(clientChannel);
+ mClientChannel = *mDispatcher->createInputChannel(name);
mConsumer = std::make_unique<InputConsumer>(mClientChannel);
}
virtual ~FakeInputReceiver() {}
sp<InputDispatcher> mDispatcher;
- std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
+ std::shared_ptr<InputChannel> mClientChannel;
std::unique_ptr<InputConsumer> mConsumer;
PreallocatedInputEventFactory mEventFactory;
};
@@ -152,14 +149,12 @@
FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
const sp<InputDispatcher>& dispatcher, const std::string name)
: FakeInputReceiver(dispatcher, name), mFrame(Rect(0, 0, WIDTH, HEIGHT)) {
- mDispatcher->registerInputChannel(mServerChannel);
-
inputApplicationHandle->updateInfo();
mInfo.applicationInfo = *inputApplicationHandle->getInfo();
}
virtual bool updateInfo() override {
- mInfo.token = mServerChannel->getConnectionToken();
+ mInfo.token = mClientChannel->getConnectionToken();
mInfo.name = "FakeWindowHandle";
mInfo.type = InputWindowInfo::Type::APPLICATION;
mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index a10da66..beacba3 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -28,8 +28,8 @@
// Log debug messages about the dispatch cycle.
#define DEBUG_DISPATCH_CYCLE 0
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
+// Log debug messages about channel creation
+#define DEBUG_CHANNEL_CREATION 0
// Log debug messages about input event injection.
#define DEBUG_INJECTION 0
@@ -351,6 +351,16 @@
}
}
+static status_t openInputChannelPair(const std::string& name,
+ std::shared_ptr<InputChannel>& serverChannel,
+ std::unique_ptr<InputChannel>& clientChannel) {
+ std::unique_ptr<InputChannel> uniqueServerChannel;
+ status_t result = InputChannel::openInputChannelPair(name, uniqueServerChannel, clientChannel);
+
+ serverChannel = std::move(uniqueServerChannel);
+ return result;
+}
+
const char* InputDispatcher::typeToString(InputDispatcher::FocusResult result) {
switch (result) {
case InputDispatcher::FocusResult::OK:
@@ -412,7 +422,7 @@
while (!mConnectionsByFd.empty()) {
sp<Connection> connection = mConnectionsByFd.begin()->second;
- unregisterInputChannel(connection->inputChannel->getConnectionToken());
+ removeInputChannel(connection->inputChannel->getConnectionToken());
}
}
@@ -2825,8 +2835,8 @@
}
}
- // Unregister the channel.
- d->unregisterInputChannelLocked(connection->inputChannel->getConnectionToken(), notify);
+ // Remove the channel.
+ d->removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify);
return 0; // remove the callback
} // release lock
}
@@ -4403,71 +4413,76 @@
}
}
-status_t InputDispatcher::registerInputChannel(const std::shared_ptr<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
+base::Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(
+ const std::string& name) {
+#if DEBUG_CHANNEL_CREATION
+ ALOGD("channel '%s' ~ createInputChannel", name.c_str());
#endif
+ std::shared_ptr<InputChannel> serverChannel;
+ std::unique_ptr<InputChannel> clientChannel;
+ status_t result = openInputChannelPair(name, serverChannel, clientChannel);
+
+ if (result) {
+ return base::Error(result) << "Failed to open input channel pair with name " << name;
+ }
+
{ // acquire lock
std::scoped_lock _l(mLock);
- sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
- if (existingConnection != nullptr) {
- ALOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().c_str());
- return BAD_VALUE;
- }
+ sp<Connection> connection = new Connection(serverChannel, false /*monitor*/, mIdGenerator);
- sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
-
- int fd = inputChannel->getFd();
+ int fd = serverChannel->getFd();
mConnectionsByFd[fd] = connection;
- mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
+ mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel;
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
- return OK;
+ return clientChannel;
}
-status_t InputDispatcher::registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
- int32_t displayId, bool isGestureMonitor) {
+base::Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(
+ int32_t displayId, bool isGestureMonitor, const std::string& name) {
+ std::shared_ptr<InputChannel> serverChannel;
+ std::unique_ptr<InputChannel> clientChannel;
+ status_t result = openInputChannelPair(name, serverChannel, clientChannel);
+ if (result) {
+ return base::Error(result) << "Failed to open input channel pair with name " << name;
+ }
+
{ // acquire lock
std::scoped_lock _l(mLock);
if (displayId < 0) {
- ALOGW("Attempted to register input monitor without a specified display.");
- return BAD_VALUE;
+ return base::Error(BAD_VALUE) << "Attempted to create input monitor with name " << name
+ << " without a specified display.";
}
- if (inputChannel->getConnectionToken() == nullptr) {
- ALOGW("Attempted to register input monitor without an identifying token.");
- return BAD_VALUE;
- }
+ sp<Connection> connection = new Connection(serverChannel, true /*monitor*/, mIdGenerator);
- sp<Connection> connection = new Connection(inputChannel, true /*monitor*/, mIdGenerator);
-
- const int fd = inputChannel->getFd();
+ const int fd = serverChannel->getFd();
mConnectionsByFd[fd] = connection;
- mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
+ mInputChannelsByToken[serverChannel->getConnectionToken()] = serverChannel;
auto& monitorsByDisplay =
isGestureMonitor ? mGestureMonitorsByDisplay : mGlobalMonitorsByDisplay;
- monitorsByDisplay[displayId].emplace_back(inputChannel);
+ monitorsByDisplay[displayId].emplace_back(serverChannel);
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
}
+
// Wake the looper because some connections have changed.
mLooper->wake();
- return OK;
+ return clientChannel;
}
-status_t InputDispatcher::unregisterInputChannel(const sp<IBinder>& connectionToken) {
+status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) {
{ // acquire lock
std::scoped_lock _l(mLock);
- status_t status = unregisterInputChannelLocked(connectionToken, false /*notify*/);
+ status_t status = removeInputChannelLocked(connectionToken, false /*notify*/);
if (status) {
return status;
}
@@ -4479,8 +4494,8 @@
return OK;
}
-status_t InputDispatcher::unregisterInputChannelLocked(const sp<IBinder>& connectionToken,
- bool notify) {
+status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connectionToken,
+ bool notify) {
sp<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
ALOGW("Attempted to unregister already unregistered input channel");
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index f3b3dda..39e57e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -116,12 +116,12 @@
virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
const sp<IBinder>& toToken) override;
- virtual status_t registerInputChannel(
- const std::shared_ptr<InputChannel>& inputChannel) override;
+ virtual base::Result<std::unique_ptr<InputChannel>> createInputChannel(
+ const std::string& name) override;
virtual void setFocusedWindow(const FocusRequest&) override;
- virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
- int32_t displayId, bool isGestureMonitor) override;
- virtual status_t unregisterInputChannel(const sp<IBinder>& connectionToken) override;
+ virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(
+ int32_t displayId, bool isGestureMonitor, const std::string& name) override;
+ virtual status_t removeInputChannel(const sp<IBinder>& connectionToken) override;
virtual status_t pilferPointers(const sp<IBinder>& token) override;
std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
@@ -513,7 +513,7 @@
void removeMonitorChannelLocked(
const sp<IBinder>& connectionToken,
std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay) REQUIRES(mLock);
- status_t unregisterInputChannelLocked(const sp<IBinder>& connectionToken, bool notify)
+ status_t removeInputChannelLocked(const sp<IBinder>& connectionToken, bool notify)
REQUIRES(mLock);
// Interesting events that we might like to log or tell the framework about.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index c3d50ea..67d9a06 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -18,6 +18,7 @@
#define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H
#include <InputListener.h>
+#include <android-base/result.h>
#include <android/FocusRequest.h>
#include <android/os/ISetInputWindowsListener.h>
#include <input/InputApplication.h>
@@ -155,13 +156,16 @@
*/
virtual void setFocusedWindow(const FocusRequest&) = 0;
- /* Registers input channels that may be used as targets for input events.
+ /**
+ * Creates an input channel that may be used as targets for input events.
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputChannel(const std::shared_ptr<InputChannel>& inputChannel) = 0;
+ virtual base::Result<std::unique_ptr<InputChannel>> createInputChannel(
+ const std::string& name) = 0;
- /* Registers input channels to be used to monitor input events.
+ /**
+ * Creates an input channel to be used to monitor input events.
*
* Each monitor must target a specific display and will only receive input events sent to that
* display. If the monitor is a gesture monitor, it will only receive pointer events on the
@@ -169,14 +173,14 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel,
- int32_t displayId, bool gestureMonitor) = 0;
+ virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(
+ int32_t displayId, bool gestureMonitor, const std::string& name) = 0;
- /* Unregister input channels that will no longer receive input events.
+ /* Removes input channels that will no longer receive input events.
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual status_t unregisterInputChannel(const sp<IBinder>& connectionToken) = 0;
+ virtual status_t removeInputChannel(const sp<IBinder>& connectionToken) = 0;
/* Allows an input monitor steal the current pointer stream away from normal input windows.
*
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 577309a..47773d9 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -48,8 +48,10 @@
const sp<ISetInputWindowsListener>&) {
return binder::Status::ok();
}
- binder::Status registerInputChannel(const InputChannel&) { return binder::Status::ok(); }
- binder::Status unregisterInputChannel(const sp<IBinder>&) { return binder::Status::ok(); }
+ binder::Status createInputChannel(const std::string&, InputChannel*) {
+ return binder::Status::ok();
+ }
+ binder::Status removeInputChannel(const sp<IBinder>&) { return binder::Status::ok(); }
binder::Status setFocusedWindow(const FocusRequest&) { return binder::Status::ok(); }
private:
diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl
index b5c5c9e..5c8a8da 100644
--- a/services/inputflinger/tests/IInputFlingerQuery.aidl
+++ b/services/inputflinger/tests/IInputFlingerQuery.aidl
@@ -26,4 +26,5 @@
void getInputWindows(out InputWindowInfo[] inputHandles);
void getInputChannels(out InputChannel[] channels);
void getLastFocusRequest(out FocusRequest request);
+ void resetInputManager();
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index ad6a602..6ef0028 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -548,10 +548,9 @@
class FakeInputReceiver {
public:
- explicit FakeInputReceiver(const std::shared_ptr<InputChannel>& clientChannel,
- const std::string name)
+ explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
: mName(name) {
- mConsumer = std::make_unique<InputConsumer>(clientChannel);
+ mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
}
InputEvent* consume() {
@@ -701,11 +700,10 @@
int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
: mName(name) {
if (token == std::nullopt) {
- std::unique_ptr<InputChannel> serverChannel, clientChannel;
- InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
- mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
- token = serverChannel->getConnectionToken();
- dispatcher->registerInputChannel(std::move(serverChannel));
+ base::Result<std::unique_ptr<InputChannel>> channel =
+ dispatcher->createInputChannel(name);
+ token = (*channel)->getConnectionToken();
+ mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
}
inputApplicationHandle->updateInfo();
@@ -1653,10 +1651,9 @@
public:
FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
int32_t displayId, bool isGestureMonitor = false) {
- std::unique_ptr<InputChannel> serverChannel, clientChannel;
- InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
- mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(clientChannel), name);
- dispatcher->registerInputMonitor(std::move(serverChannel), displayId, isGestureMonitor);
+ base::Result<std::unique_ptr<InputChannel>> channel =
+ dispatcher->createInputMonitor(displayId, isGestureMonitor, name);
+ mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
}
sp<IBinder> getToken() { return mInputReceiver->getToken(); }
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index 3aef1e4..c368e79 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -135,7 +135,6 @@
public:
TestInputManager(){};
- void checkFdFlags(const android::base::unique_fd& fd);
binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles);
binder::Status getInputChannels(std::vector<::android::InputChannel>* channels);
@@ -147,10 +146,12 @@
const std::vector<InputWindowInfo>& handles,
const sp<ISetInputWindowsListener>& setInputWindowsListener) override;
- binder::Status registerInputChannel(const InputChannel& channel) override;
- binder::Status unregisterInputChannel(const sp<IBinder>& connectionToken) override;
+ binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
+ binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
binder::Status setFocusedWindow(const FocusRequest&) override;
+ void reset();
+
private:
mutable Mutex mLock;
std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay;
@@ -164,6 +165,7 @@
binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override;
binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override;
binder::Status getLastFocusRequest(FocusRequest*) override;
+ binder::Status resetInputManager() override;
private:
sp<android::TestInputManager> mManager;
@@ -182,6 +184,11 @@
return mManager->getLastFocusRequest(request);
}
+binder::Status TestInputQuery::resetInputManager() {
+ mManager->reset();
+ return binder::Status::ok();
+}
+
binder::Status SetInputWindowsListener::onSetInputWindowsFinished() {
if (mCbFunc != nullptr) {
mCbFunc();
@@ -204,23 +211,21 @@
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 InputChannel& channel) {
+binder::Status TestInputManager::createInputChannel(const std::string& name,
+ InputChannel* outChannel) {
AutoMutex _l(mLock);
- // check Fd flags
- checkFdFlags(channel.getFd());
+ std::unique_ptr<InputChannel> serverChannel;
+ std::unique_ptr<InputChannel> clientChannel;
+ InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
- mInputChannels.push_back(channel.dup());
+ clientChannel->copyTo(*outChannel);
+
+ mInputChannels.emplace_back(std::move(serverChannel));
return binder::Status::ok();
}
-binder::Status TestInputManager::unregisterInputChannel(const sp<IBinder>& connectionToken) {
+binder::Status TestInputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
AutoMutex _l(mLock);
auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(),
@@ -271,6 +276,12 @@
return binder::Status::ok();
}
+void TestInputManager::reset() {
+ mHandlesPerDisplay.clear();
+ mInputChannels.clear();
+ mFocusRequest = FocusRequest();
+}
+
void InputFlingerServiceTest::SetUp() {
mSetInputWindowsListener = new SetInputWindowsListener([&]() {
std::unique_lock<std::mutex> lock(mLock);
@@ -316,7 +327,9 @@
InitializeInputFlinger();
}
-void InputFlingerServiceTest::TearDown() {}
+void InputFlingerServiceTest::TearDown() {
+ mQuery->resetInputManager();
+}
void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const {
EXPECT_EQ(mInfo, info);
@@ -367,45 +380,33 @@
}
/**
- * Test InputFlinger service interface registerInputChannel
+ * Test InputFlinger service interface createInputChannel
*/
-TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) {
- std::unique_ptr<InputChannel> serverChannel, clientChannel;
+TEST_F(InputFlingerServiceTest, CreateInputChannelReturnsUnblockedFd) {
+ // Test that the unblocked file descriptor flag is kept across processes over binder
+ // transactions.
- InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
- mService->registerInputChannel(*serverChannel);
+ InputChannel channel;
+ ASSERT_TRUE(mService->createInputChannel("testchannels", &channel).isOk());
+
+ const base::unique_fd& fd = channel.getFd();
+ ASSERT_TRUE(fd.ok());
+
+ const int result = fcntl(fd, F_GETFL);
+ EXPECT_NE(result, -1);
+ EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
+}
+
+TEST_F(InputFlingerServiceTest, InputWindow_CreateInputChannel) {
+ InputChannel channel;
+ ASSERT_TRUE(mService->createInputChannel("testchannels", &channel).isOk());
std::vector<::android::InputChannel> channels;
mQuery->getInputChannels(&channels);
ASSERT_EQ(channels.size(), 1UL);
- EXPECT_EQ(channels[0], *serverChannel);
+ EXPECT_EQ(channels[0].getConnectionToken(), channel.getConnectionToken());
- mService->unregisterInputChannel(serverChannel->getConnectionToken());
- mQuery->getInputChannels(&channels);
- EXPECT_EQ(channels.size(), 0UL);
-}
-
-/**
- * Test InputFlinger service interface registerInputChannel with invalid cases
- */
-TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) {
- std::unique_ptr<InputChannel> serverChannel, clientChannel;
- InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel);
-
- std::vector<::android::InputChannel> channels;
- mQuery->getInputChannels(&channels);
- EXPECT_EQ(channels.size(), 0UL);
-
- mService->registerInputChannel(InputChannel());
- mService->unregisterInputChannel(clientChannel->getConnectionToken());
-
- mService->registerInputChannel(*serverChannel);
- mService->registerInputChannel(*clientChannel);
- mQuery->getInputChannels(&channels);
- EXPECT_EQ(channels.size(), 2UL);
-
- mService->unregisterInputChannel(clientChannel->getConnectionToken());
- mService->unregisterInputChannel(serverChannel->getConnectionToken());
+ mService->removeInputChannel(channel.getConnectionToken());
mQuery->getInputChannels(&channels);
EXPECT_EQ(channels.size(), 0UL);
}