2020#include < time.h>
2121#include < errno.h>
2222
23+ #include < android-base/logging.h>
2324#include < binder/Binder.h>
2425#include < binder/Parcel.h>
2526#include < gtest/gtest.h>
@@ -43,6 +44,39 @@ bool operator==(const InputChannel& left, const InputChannel& right) {
4344 return left.getName () == right.getName () &&
4445 left.getConnectionToken () == right.getConnectionToken () && lhs.st_ino == rhs.st_ino ;
4546}
47+
48+ /* *
49+ * Read a message from the provided channel. Read will continue until there's data, so only call
50+ * this if there's data in the channel, or it's closed. If there's no data, this will loop forever.
51+ */
52+ android::base::Result<InputMessage> readMessage (InputChannel& channel) {
53+ while (true ) {
54+ // Keep reading until we get something other than 'WOULD_BLOCK'
55+ android::base::Result<InputMessage> result = channel.receiveMessage ();
56+ if (!result.ok () && result.error ().code () == WOULD_BLOCK) {
57+ // The data is not available yet.
58+ continue ; // try again
59+ }
60+ return result;
61+ }
62+ }
63+
64+ InputMessage createFinishedMessage (uint32_t seq) {
65+ InputMessage finish{};
66+ finish.header .type = InputMessage::Type::FINISHED;
67+ finish.header .seq = seq;
68+ finish.body .finished .handled = true ;
69+ return finish;
70+ }
71+
72+ InputMessage createKeyMessage (uint32_t seq) {
73+ InputMessage key{};
74+ key.header .type = InputMessage::Type::KEY;
75+ key.header .seq = seq;
76+ key.body .key .action = AKEY_EVENT_ACTION_DOWN;
77+ return key;
78+ }
79+
4680} // namespace
4781
4882class InputChannelTest : public testing ::Test {
@@ -227,6 +261,120 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) {
227261 }
228262}
229263
264+ /* *
265+ * In this test, server writes 3 key events to the client. The client, upon receiving the first key,
266+ * sends a "finished" signal back to server, and then closes the fd.
267+ *
268+ * Next, we check what the server receives.
269+ *
270+ * In most cases, the server will receive the finish event, and then an 'fd closed' event.
271+ *
272+ * However, sometimes, the 'finish' event will not be delivered to the server. This is communicated
273+ * to the server via 'ECONNRESET', which the InputChannel converts into DEAD_OBJECT.
274+ *
275+ * The server needs to be aware of this behaviour and correctly clean up any state associated with
276+ * the client, even if the client did not end up finishing some of the messages.
277+ *
278+ * This test is written to expose a behaviour on the linux side - occasionally, the
279+ * last events written to the fd by the consumer are not delivered to the server.
280+ *
281+ * When tested on 2025 hardware, ECONNRESET was received approximately 1 out of 40 tries.
282+ * In vast majority (~ 29999 / 30000) of cases, after receiving ECONNRESET, the server could still
283+ * read the client data after receiving ECONNRESET.
284+ */
285+ TEST_F (InputChannelTest, ReceiveAfterCloseMultiThreaded) {
286+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
287+ status_t result =
288+ InputChannel::openInputChannelPair (" channel name" , serverChannel, clientChannel);
289+ ASSERT_EQ (OK, result) << " should have successfully opened a channel pair" ;
290+
291+ // Sender / publisher: publish 3 keys
292+ InputMessage key1 = createKeyMessage (/* seq=*/ 1 );
293+ serverChannel->sendMessage (&key1);
294+ // The client should close the fd after it reads this one, but we will send 2 more here.
295+ InputMessage key2 = createKeyMessage (/* seq=*/ 2 );
296+ serverChannel->sendMessage (&key2);
297+ InputMessage key3 = createKeyMessage (/* seq=*/ 3 );
298+ serverChannel->sendMessage (&key3);
299+
300+ std::thread consumer = std::thread ([clientChannel = std::move (clientChannel)]() mutable {
301+ // Read the first key
302+ android::base::Result<InputMessage> firstKey = readMessage (*clientChannel);
303+ if (!firstKey.ok ()) {
304+ FAIL () << " Did not receive the first key" ;
305+ }
306+
307+ // Send finish
308+ const InputMessage finish = createFinishedMessage (firstKey->header .seq );
309+ clientChannel->sendMessage (&finish);
310+ // Now close the fd
311+ clientChannel.reset ();
312+ });
313+
314+ // Now try to read the finish message, even though client closed the fd
315+ android::base::Result<InputMessage> response = readMessage (*serverChannel);
316+ consumer.join ();
317+ if (response.ok ()) {
318+ ASSERT_EQ (response->header .type , InputMessage::Type::FINISHED);
319+ } else {
320+ // It's possible that after the client closes the fd, server will receive ECONNRESET.
321+ // In those situations, this error code will be translated into DEAD_OBJECT by the
322+ // InputChannel.
323+ ASSERT_EQ (response.error ().code (), DEAD_OBJECT);
324+ // In most cases, subsequent attempts to read the client channel at this
325+ // point would succeed. However, for simplicity, we exit here (since
326+ // it's not guaranteed).
327+ return ;
328+ }
329+
330+ // There should not be any more events from the client, since the client closed fd after the
331+ // first key.
332+ android::base::Result<InputMessage> noEvent = serverChannel->receiveMessage ();
333+ ASSERT_FALSE (noEvent.ok ()) << " Got event " << *noEvent;
334+ }
335+
336+ /* *
337+ * Similar test as above, but single-threaded.
338+ */
339+ TEST_F (InputChannelTest, ReceiveAfterCloseSingleThreaded) {
340+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
341+ status_t result =
342+ InputChannel::openInputChannelPair (" channel name" , serverChannel, clientChannel);
343+ ASSERT_EQ (OK, result) << " should have successfully opened a channel pair" ;
344+
345+ // Sender / publisher: publish 3 keys
346+ InputMessage key1 = createKeyMessage (/* seq=*/ 1 );
347+ serverChannel->sendMessage (&key1);
348+ // The client should close the fd after it reads this one, but we will send 2 more here.
349+ InputMessage key2 = createKeyMessage (/* seq=*/ 2 );
350+ serverChannel->sendMessage (&key2);
351+ InputMessage key3 = createKeyMessage (/* seq=*/ 3 );
352+ serverChannel->sendMessage (&key3);
353+
354+ // Read the first key
355+ android::base::Result<InputMessage> firstKey = readMessage (*clientChannel);
356+ if (!firstKey.ok ()) {
357+ FAIL () << " Did not receive the first key" ;
358+ }
359+
360+ // Send finish
361+ const InputMessage finish = createFinishedMessage (firstKey->header .seq );
362+ clientChannel->sendMessage (&finish);
363+ // Now close the fd
364+ clientChannel.reset ();
365+
366+ // Now try to read the finish message, even though client closed the fd
367+ android::base::Result<InputMessage> response = readMessage (*serverChannel);
368+ ASSERT_FALSE (response.ok ());
369+ ASSERT_EQ (response.error ().code (), DEAD_OBJECT);
370+
371+ // We can still read the finish event (but in practice, the expectation is that the server will
372+ // not be doing this after getting DEAD_OBJECT).
373+ android::base::Result<InputMessage> finishEvent = serverChannel->receiveMessage ();
374+ ASSERT_TRUE (finishEvent.ok ());
375+ ASSERT_EQ (finishEvent->header .type , InputMessage::Type::FINISHED);
376+ }
377+
230378TEST_F (InputChannelTest, DuplicateChannelAndAssertEqual) {
231379 std::unique_ptr<InputChannel> serverChannel, clientChannel;
232380
0 commit comments