From fdb37a5bf7a8330f0fbbf3f455f4367057b429ac Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 1 Apr 2024 14:13:24 -0700 Subject: [PATCH 1/4] Add a flag to record the screen. --- .../scenario_app/bin/run_android_tests.dart | 25 ++++++++++++++++++- testing/scenario_app/bin/utils/options.dart | 8 ++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/testing/scenario_app/bin/run_android_tests.dart b/testing/scenario_app/bin/run_android_tests.dart index 71ff683d40b10..9f4b191f687e7 100644 --- a/testing/scenario_app/bin/run_android_tests.dart +++ b/testing/scenario_app/bin/run_android_tests.dart @@ -91,6 +91,7 @@ void main(List args) async { ndkStack: options.ndkStack, forceSurfaceProducerSurfaceTexture: options.forceSurfaceProducerSurfaceTexture, prefixLogsPerRun: options.prefixLogsPerRun, + recordScreen: options.recordScreen, ); onSigint.cancel(); exit(0); @@ -135,6 +136,7 @@ Future _run({ required String ndkStack, required bool forceSurfaceProducerSurfaceTexture, required bool prefixLogsPerRun, + required bool recordScreen, }) async { const ProcessManager pm = LocalProcessManager(); final String scenarioAppPath = join(outDir.path, 'scenario_app'); @@ -230,6 +232,7 @@ Future _run({ late Process logcatProcess; late Future logcatProcessExitCode; _ImpellerBackend? actualImpellerBackend; + Process? screenRecordProcess; final IOSink logcat = File(logcatPath).openWrite(); try { @@ -361,6 +364,19 @@ Future _run({ } }); + if (recordScreen) { + await step('Recording screen...', () async { + final String screenRecordingPath = join(logsDir.path, 'screen.mp4'); + screenRecordProcess = await pm.start([ + adb.path, + 'shell', + 'screenrecord', + screenRecordingPath, + ]); + log('writing screen recording to $screenRecordingPath'); + }); + } + await step('Running instrumented tests...', () async { final (int exitCode, StringBuffer out) = await pm.runAndCapture([ adb.path, @@ -368,7 +384,7 @@ Future _run({ 'am', 'instrument', '-w', - '--no-window-animation', + '--no-window-animation', if (smokeTestFullPath != null) '-e class $smokeTestFullPath', if (enableImpeller) @@ -447,6 +463,13 @@ Future _run({ } }); + if (screenRecordProcess != null) { + await step('Killing screen recording process...', () async { + screenRecordProcess!.kill(ProcessSignal.sigkill); + await screenRecordProcess!.exitCode; + }); + } + await step('Killing logcat process...', () async { final bool delivered = logcatProcess.kill(ProcessSignal.sigkill); assert(delivered); diff --git a/testing/scenario_app/bin/utils/options.dart b/testing/scenario_app/bin/utils/options.dart index 36364cf83ba39..e1c785a42f767 100644 --- a/testing/scenario_app/bin/utils/options.dart +++ b/testing/scenario_app/bin/utils/options.dart @@ -165,6 +165,11 @@ extension type const Options._(ArgResults _args) { defaultsTo: environment.isCi, hide: hideUnusualOptions, ) + ..addFlag( + 'record-screen', + help: 'Whether to record the screen during the test run.', + defaultsTo: environment.isCi, + ) ..addOption( 'impeller-backend', help: 'The graphics backend to use when --enable-impeller is true. ' @@ -286,6 +291,9 @@ extension type const Options._(ArgResults _args) { /// Whether to enable Impeller as the graphics backend. bool get enableImpeller => _args['enable-impeller'] as bool; + /// Whether to record the screen during the test run. + bool get recordScreen => _args['record-screen'] as bool; + /// The graphics backend to use when --enable-impeller is true. String get impellerBackend => _args['impeller-backend'] as String; From b26fe288ab27102d2b9fed348ffc5b7252e88462 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 1 Apr 2024 14:54:14 -0700 Subject: [PATCH 2/4] Working screen record. --- .../scenario_app/bin/run_android_tests.dart | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/testing/scenario_app/bin/run_android_tests.dart b/testing/scenario_app/bin/run_android_tests.dart index 9f4b191f687e7..a849bfd15b096 100644 --- a/testing/scenario_app/bin/run_android_tests.dart +++ b/testing/scenario_app/bin/run_android_tests.dart @@ -366,11 +366,28 @@ Future _run({ if (recordScreen) { await step('Recording screen...', () async { - final String screenRecordingPath = join(logsDir.path, 'screen.mp4'); + // Create a /tmp directory on the device to store the screen recording. + final int exitCode = await pm.runAndForward([ + adb.path, + 'shell', + 'mkdir', + '-p', + join(_emulatorStoragePath, 'tmp'), + ]); + if (exitCode != 0) { + panic(['could not create /tmp directory on device']); + } + final String screenRecordingPath = join( + _emulatorStoragePath, + 'tmp', + 'screen.mp4', + ); screenRecordProcess = await pm.start([ adb.path, 'shell', 'screenrecord', + '--time-limit=0', + '--bugreport', screenRecordingPath, ]); log('writing screen recording to $screenRecordingPath'); @@ -465,8 +482,42 @@ Future _run({ if (screenRecordProcess != null) { await step('Killing screen recording process...', () async { + // Kill the screen recording process. screenRecordProcess!.kill(ProcessSignal.sigkill); await screenRecordProcess!.exitCode; + + // Pull the screen recording from the device. + final String screenRecordingPath = join( + _emulatorStoragePath, + 'tmp', + 'screen.mp4', + ); + final String screenRecordingLocalPath = join( + logsDir.path, + 'screen.mp4', + ); + final int exitCode = await pm.runAndForward([ + adb.path, + 'pull', + screenRecordingPath, + screenRecordingLocalPath, + ]); + if (exitCode != 0) { + logError('could not pull screen recording from device'); + } + + log('wrote screen recording to $screenRecordingLocalPath'); + + // Remove the screen recording from the device. + final int removeExitCode = await pm.runAndForward([ + adb.path, + 'shell', + 'rm', + screenRecordingPath, + ]); + if (removeExitCode != 0) { + logError('could not remove screen recording from device'); + } }); } @@ -559,6 +610,8 @@ Future _run({ } } +const String _emulatorStoragePath = '/storage/emulated/0/Download'; + void _withTemporaryCwd(String path, void Function() callback) { final String originalCwd = Directory.current.path; Directory.current = Directory(path).path; From 1da9a2ea74c4ff750cf8bec76d5c9b963685d373 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 1 Apr 2024 14:54:36 -0700 Subject: [PATCH 3/4] Fmt. --- testing/scenario_app/bin/run_android_tests.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/scenario_app/bin/run_android_tests.dart b/testing/scenario_app/bin/run_android_tests.dart index a849bfd15b096..b3381cbd9bbfa 100644 --- a/testing/scenario_app/bin/run_android_tests.dart +++ b/testing/scenario_app/bin/run_android_tests.dart @@ -488,8 +488,8 @@ Future _run({ // Pull the screen recording from the device. final String screenRecordingPath = join( - _emulatorStoragePath, - 'tmp', + _emulatorStoragePath, + 'tmp', 'screen.mp4', ); final String screenRecordingLocalPath = join( From 0a4caf221c6a8d54379276a9d0f7ba1cf7ee0bf9 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 1 Apr 2024 14:59:47 -0700 Subject: [PATCH 4/4] ++ --- testing/scenario_app/bin/run_android_tests.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/scenario_app/bin/run_android_tests.dart b/testing/scenario_app/bin/run_android_tests.dart index b3381cbd9bbfa..a4782f31cf9b1 100644 --- a/testing/scenario_app/bin/run_android_tests.dart +++ b/testing/scenario_app/bin/run_android_tests.dart @@ -401,7 +401,7 @@ Future _run({ 'am', 'instrument', '-w', - '--no-window-animation', + '--no-window-animation', if (smokeTestFullPath != null) '-e class $smokeTestFullPath', if (enableImpeller)