summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2024-09-17 14:20:57 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-09-17 14:20:57 +0000
commit1f812c59932aa61f9d30913fbc02b81070f7f6ac (patch)
tree0081d2f7bb32ebc3f09078bf38baad999c50c0bb
parent5fa0f5ada0df31bc9731f74b73b6379e867b355f (diff)
parentd67b1f8337794d3aacfd12ecd5934f7a35731ef2 (diff)
Merge "UinputRecordingIntegrationTests: Extend device lifetime to avoid racing" into main
-rw-r--r--tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt50
1 files changed, 34 insertions, 16 deletions
diff --git a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
index aa73c397a663..c61a25021949 100644
--- a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
+++ b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
@@ -36,7 +36,6 @@ import com.android.cts.input.inputeventmatchers.withMotionAction
import com.android.cts.input.inputeventmatchers.withPressure
import com.android.cts.input.inputeventmatchers.withRawCoords
import com.android.cts.input.inputeventmatchers.withSource
-import java.io.InputStream
import junit.framework.Assert.fail
import org.hamcrest.Matchers.allOf
import org.junit.Before
@@ -130,17 +129,18 @@ class UinputRecordingIntegrationTests {
scenario.virtualDisplay.display.uniqueId!!,
)
- injectUinputEvents()
-
- if (DEBUG_RECEIVED_EVENTS) {
- printReceivedEventsToLogcat(scenario.activity)
- fail("Test cannot pass in debug mode!")
+ injectUinputEvents().use {
+ if (DEBUG_RECEIVED_EVENTS) {
+ printReceivedEventsToLogcat(scenario.activity)
+ fail("Test cannot pass in debug mode!")
+ }
+
+ val verifier = EventVerifier(
+ BatchedEventSplitter { scenario.activity.getInputEvent() }
+ )
+ verifyEvents(verifier)
+ scenario.activity.assertNoEvents()
}
-
- val verifier =
- EventVerifier(BatchedEventSplitter { scenario.activity.getInputEvent() })
- verifyEvents(verifier)
- scenario.activity.assertNoEvents()
} finally {
inputManager.removeUniqueIdAssociationByPort(inputPort)
}
@@ -162,14 +162,32 @@ class UinputRecordingIntegrationTests {
}
}
- private fun injectUinputEvents() {
+ /**
+ * Plays back the evemu recording associated with the current test case by injecting it via
+ * the `uinput` shell command in interactive mode. The recording playback will begin
+ * immediately, and the shell command (and the associated input device) will remain alive
+ * until the returned [AutoCloseable] is closed.
+ */
+ private fun injectUinputEvents(): AutoCloseable {
val fds = instrumentation.uiAutomation!!.executeShellCommandRw("uinput -")
+ // We do not need to use stdout in this test.
+ fds[0].close()
- ParcelFileDescriptor.AutoCloseOutputStream(fds[1]).use { stdIn ->
- val inputStream: InputStream = instrumentation.context.resources.openRawResource(
+ return ParcelFileDescriptor.AutoCloseOutputStream(fds[1]).also { stdin ->
+ instrumentation.context.resources.openRawResource(
testData.uinputRecordingResource,
- )
- stdIn.write(inputStream.readBytes())
+ ).use { inputStream ->
+ stdin.write(inputStream.readBytes())
+
+ // TODO(b/367419268): Remove extra event injection when uinput parsing is fixed.
+ // Inject an extra sync event with an arbitrarily large timestamp, because the
+ // uinput command will not process the last event until either the next event is
+ // parsed, or fd is closed. Injecting this sync allows us complete injection of
+ // the evemu recording and extend the lifetime of the input device by keeping this
+ // fd open.
+ stdin.write("\nE: 9999.99 0 0 0\n".toByteArray())
+ stdin.flush()
+ }
}
}