diff options
| author | 2024-09-17 14:20:57 +0000 | |
|---|---|---|
| committer | 2024-09-17 14:20:57 +0000 | |
| commit | 1f812c59932aa61f9d30913fbc02b81070f7f6ac (patch) | |
| tree | 0081d2f7bb32ebc3f09078bf38baad999c50c0bb | |
| parent | 5fa0f5ada0df31bc9731f74b73b6379e867b355f (diff) | |
| parent | d67b1f8337794d3aacfd12ecd5934f7a35731ef2 (diff) | |
Merge "UinputRecordingIntegrationTests: Extend device lifetime to avoid racing" into main
| -rw-r--r-- | tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt | 50 |
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() + } } } |