Loading include/input/InputTransport.h +14 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,13 @@ public: */ status_t receiveMessage(InputMessage* msg); /* Tells whether there is a message in the channel available to be received. * * This is only a performance hint and may return false negative results. Clients should not * rely on availability of the message based on the return value. */ bool probablyHasInput() const; /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; Loading Loading @@ -518,6 +525,13 @@ public: */ int32_t getPendingBatchSource() const; /* Returns true when there is *likely* a pending batch or a pending event in the channel. * * This is only a performance hint and may return false negative results. Clients should not * rely on availability of the message based on the return value. */ bool probablyHasInput() const; std::string dump() const; private: Loading libs/input/InputTransport.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <fcntl.h> #include <inttypes.h> #include <math.h> #include <poll.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> Loading Loading @@ -517,6 +518,22 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { return OK; } bool InputChannel::probablyHasInput() const { struct pollfd pfds = {.fd = mFd, .events = POLLIN}; if (::poll(&pfds, /*nfds=*/1, /*timeout=*/0) <= 0) { // This can be a false negative because EAGAIN and ENOMEM are not handled. The latter should // be extremely rare. The EAGAIN is also unlikely because it happens only when the signal // arrives while the syscall is executed, and the syscall is quick. Hitting EAGAIN too often // would be a sign of having too many signals, which is a bigger performance problem. A // common tradition is to repeat the syscall on each EAGAIN, but it is not necessary here. // In other words, the missing one liner is replaced by a multiline explanation. return false; } // From poll(2): The bits returned in |revents| can include any of those specified in |events|, // or one of the values POLLERR, POLLHUP, or POLLNVAL. return (pfds.revents & POLLIN) != 0; } std::unique_ptr<InputChannel> InputChannel::dup() const { base::unique_fd newFd(dupFd()); return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); Loading Loading @@ -1406,6 +1423,10 @@ int32_t InputConsumer::getPendingBatchSource() const { return head.body.motion.source; } bool InputConsumer::probablyHasInput() const { return hasPendingBatch() || mChannel->probablyHasInput(); } ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const { for (size_t i = 0; i < mBatches.size(); i++) { const Batch& batch = mBatches[i]; Loading libs/input/tests/InputChannel_test.cpp +44 −4 Original line number Diff line number Diff line Loading @@ -81,8 +81,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "client channel should have suffixed name"; // Server->Client communication InputMessage serverMsg; memset(&serverMsg, 0, sizeof(InputMessage)); InputMessage serverMsg = {}; serverMsg.header.type = InputMessage::Type::KEY; serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) Loading @@ -97,8 +96,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "client channel should receive the correct message from server channel"; // Client->Server communication InputMessage clientReply; memset(&clientReply, 0, sizeof(InputMessage)); InputMessage clientReply = {}; clientReply.header.type = InputMessage::Type::FINISHED; clientReply.header.seq = 0x11223344; clientReply.body.finished.handled = true; Loading @@ -116,6 +114,48 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "server channel should receive the correct message from client channel"; } TEST_F(InputChannelTest, ProbablyHasInput) { std::unique_ptr<InputChannel> senderChannel, receiverChannel; // Open a pair of channels. status_t result = InputChannel::openInputChannelPair("channel name", senderChannel, receiverChannel); ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; ASSERT_FALSE(receiverChannel->probablyHasInput()); // Send one message. InputMessage serverMsg = {}; serverMsg.header.type = InputMessage::Type::KEY; serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; EXPECT_EQ(OK, senderChannel->sendMessage(&serverMsg)) << "server channel should be able to send message to client channel"; // Verify input is available. bool hasInput = false; do { // The probablyHasInput() can return false positive under rare circumstances uncontrollable // by the tests. Re-request the availability in this case. Returning |false| for a long // time is not intended, and would cause a test timeout. hasInput = receiverChannel->probablyHasInput(); } while (!hasInput); EXPECT_TRUE(hasInput) << "client channel should observe that message is available before receiving it"; // Receive (consume) the message. InputMessage clientMsg; EXPECT_EQ(OK, receiverChannel->receiveMessage(&clientMsg)) << "client channel should be able to receive message from server channel"; EXPECT_EQ(serverMsg.header.type, clientMsg.header.type) << "client channel should receive the correct message from server channel"; EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action) << "client channel should receive the correct message from server channel"; // Verify input is not available. EXPECT_FALSE(receiverChannel->probablyHasInput()) << "client should not observe any more messages after receiving the single one"; } TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { std::unique_ptr<InputChannel> serverChannel, clientChannel; Loading libs/input/tests/InputPublisherAndConsumer_test.cpp +221 −166 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
include/input/InputTransport.h +14 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,13 @@ public: */ status_t receiveMessage(InputMessage* msg); /* Tells whether there is a message in the channel available to be received. * * This is only a performance hint and may return false negative results. Clients should not * rely on availability of the message based on the return value. */ bool probablyHasInput() const; /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; Loading Loading @@ -518,6 +525,13 @@ public: */ int32_t getPendingBatchSource() const; /* Returns true when there is *likely* a pending batch or a pending event in the channel. * * This is only a performance hint and may return false negative results. Clients should not * rely on availability of the message based on the return value. */ bool probablyHasInput() const; std::string dump() const; private: Loading
libs/input/InputTransport.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <fcntl.h> #include <inttypes.h> #include <math.h> #include <poll.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> Loading Loading @@ -517,6 +518,22 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { return OK; } bool InputChannel::probablyHasInput() const { struct pollfd pfds = {.fd = mFd, .events = POLLIN}; if (::poll(&pfds, /*nfds=*/1, /*timeout=*/0) <= 0) { // This can be a false negative because EAGAIN and ENOMEM are not handled. The latter should // be extremely rare. The EAGAIN is also unlikely because it happens only when the signal // arrives while the syscall is executed, and the syscall is quick. Hitting EAGAIN too often // would be a sign of having too many signals, which is a bigger performance problem. A // common tradition is to repeat the syscall on each EAGAIN, but it is not necessary here. // In other words, the missing one liner is replaced by a multiline explanation. return false; } // From poll(2): The bits returned in |revents| can include any of those specified in |events|, // or one of the values POLLERR, POLLHUP, or POLLNVAL. return (pfds.revents & POLLIN) != 0; } std::unique_ptr<InputChannel> InputChannel::dup() const { base::unique_fd newFd(dupFd()); return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); Loading Loading @@ -1406,6 +1423,10 @@ int32_t InputConsumer::getPendingBatchSource() const { return head.body.motion.source; } bool InputConsumer::probablyHasInput() const { return hasPendingBatch() || mChannel->probablyHasInput(); } ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const { for (size_t i = 0; i < mBatches.size(); i++) { const Batch& batch = mBatches[i]; Loading
libs/input/tests/InputChannel_test.cpp +44 −4 Original line number Diff line number Diff line Loading @@ -81,8 +81,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "client channel should have suffixed name"; // Server->Client communication InputMessage serverMsg; memset(&serverMsg, 0, sizeof(InputMessage)); InputMessage serverMsg = {}; serverMsg.header.type = InputMessage::Type::KEY; serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) Loading @@ -97,8 +96,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "client channel should receive the correct message from server channel"; // Client->Server communication InputMessage clientReply; memset(&clientReply, 0, sizeof(InputMessage)); InputMessage clientReply = {}; clientReply.header.type = InputMessage::Type::FINISHED; clientReply.header.seq = 0x11223344; clientReply.body.finished.handled = true; Loading @@ -116,6 +114,48 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { << "server channel should receive the correct message from client channel"; } TEST_F(InputChannelTest, ProbablyHasInput) { std::unique_ptr<InputChannel> senderChannel, receiverChannel; // Open a pair of channels. status_t result = InputChannel::openInputChannelPair("channel name", senderChannel, receiverChannel); ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; ASSERT_FALSE(receiverChannel->probablyHasInput()); // Send one message. InputMessage serverMsg = {}; serverMsg.header.type = InputMessage::Type::KEY; serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; EXPECT_EQ(OK, senderChannel->sendMessage(&serverMsg)) << "server channel should be able to send message to client channel"; // Verify input is available. bool hasInput = false; do { // The probablyHasInput() can return false positive under rare circumstances uncontrollable // by the tests. Re-request the availability in this case. Returning |false| for a long // time is not intended, and would cause a test timeout. hasInput = receiverChannel->probablyHasInput(); } while (!hasInput); EXPECT_TRUE(hasInput) << "client channel should observe that message is available before receiving it"; // Receive (consume) the message. InputMessage clientMsg; EXPECT_EQ(OK, receiverChannel->receiveMessage(&clientMsg)) << "client channel should be able to receive message from server channel"; EXPECT_EQ(serverMsg.header.type, clientMsg.header.type) << "client channel should receive the correct message from server channel"; EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action) << "client channel should receive the correct message from server channel"; // Verify input is not available. EXPECT_FALSE(receiverChannel->probablyHasInput()) << "client should not observe any more messages after receiving the single one"; } TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { std::unique_ptr<InputChannel> serverChannel, clientChannel; Loading
libs/input/tests/InputPublisherAndConsumer_test.cpp +221 −166 File changed.Preview size limit exceeded, changes collapsed. Show changes