Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b03b80e

Browse files
authored
Run and record adb shell screenrecord during Android scenario app (#51832)
More grasping at straws to solve flutter/flutter#145988. At some point this could be moved to `--verbose` if it isn't useful. This will automatically be copied into `${FLUTTER_LOGS_DIR}`, yay! Example: https://github.com/flutter/engine/assets/168174/c8caca7a-88ec-4d09-88bd-ebfc531f6512
1 parent 6c8558f commit b03b80e

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

testing/scenario_app/bin/run_android_tests.dart

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ void main(List<String> args) async {
9191
ndkStack: options.ndkStack,
9292
forceSurfaceProducerSurfaceTexture: options.forceSurfaceProducerSurfaceTexture,
9393
prefixLogsPerRun: options.prefixLogsPerRun,
94+
recordScreen: options.recordScreen,
9495
);
9596
onSigint.cancel();
9697
exit(0);
@@ -135,6 +136,7 @@ Future<void> _run({
135136
required String ndkStack,
136137
required bool forceSurfaceProducerSurfaceTexture,
137138
required bool prefixLogsPerRun,
139+
required bool recordScreen,
138140
}) async {
139141
const ProcessManager pm = LocalProcessManager();
140142
final String scenarioAppPath = join(outDir.path, 'scenario_app');
@@ -230,6 +232,7 @@ Future<void> _run({
230232
late Process logcatProcess;
231233
late Future<int> logcatProcessExitCode;
232234
_ImpellerBackend? actualImpellerBackend;
235+
Process? screenRecordProcess;
233236

234237
final IOSink logcat = File(logcatPath).openWrite();
235238
try {
@@ -361,14 +364,44 @@ Future<void> _run({
361364
}
362365
});
363366

367+
if (recordScreen) {
368+
await step('Recording screen...', () async {
369+
// Create a /tmp directory on the device to store the screen recording.
370+
final int exitCode = await pm.runAndForward(<String>[
371+
adb.path,
372+
'shell',
373+
'mkdir',
374+
'-p',
375+
join(_emulatorStoragePath, 'tmp'),
376+
]);
377+
if (exitCode != 0) {
378+
panic(<String>['could not create /tmp directory on device']);
379+
}
380+
final String screenRecordingPath = join(
381+
_emulatorStoragePath,
382+
'tmp',
383+
'screen.mp4',
384+
);
385+
screenRecordProcess = await pm.start(<String>[
386+
adb.path,
387+
'shell',
388+
'screenrecord',
389+
'--time-limit=0',
390+
'--bugreport',
391+
screenRecordingPath,
392+
]);
393+
log('writing screen recording to $screenRecordingPath');
394+
});
395+
}
396+
364397
await step('Running instrumented tests...', () async {
365398
final (int exitCode, StringBuffer out) = await pm.runAndCapture(<String>[
366399
adb.path,
367400
'shell',
368401
'am',
369402
'instrument',
370403
'-w',
371-
'--no-window-animation',
404+
'--no-window-animation',
372405
if (smokeTestFullPath != null)
373406
'-e class $smokeTestFullPath',
374407
if (enableImpeller)
@@ -447,6 +480,47 @@ Future<void> _run({
447480
}
448481
});
449482

483+
if (screenRecordProcess != null) {
484+
await step('Killing screen recording process...', () async {
485+
// Kill the screen recording process.
486+
screenRecordProcess!.kill(ProcessSignal.sigkill);
487+
await screenRecordProcess!.exitCode;
488+
489+
// Pull the screen recording from the device.
490+
final String screenRecordingPath = join(
491+
_emulatorStoragePath,
492+
'tmp',
493+
'screen.mp4',
494+
);
495+
final String screenRecordingLocalPath = join(
496+
logsDir.path,
497+
'screen.mp4',
498+
);
499+
final int exitCode = await pm.runAndForward(<String>[
500+
adb.path,
501+
'pull',
502+
screenRecordingPath,
503+
screenRecordingLocalPath,
504+
]);
505+
if (exitCode != 0) {
506+
logError('could not pull screen recording from device');
507+
}
508+
509+
log('wrote screen recording to $screenRecordingLocalPath');
510+
511+
// Remove the screen recording from the device.
512+
final int removeExitCode = await pm.runAndForward(<String>[
513+
adb.path,
514+
'shell',
515+
'rm',
516+
screenRecordingPath,
517+
]);
518+
if (removeExitCode != 0) {
519+
logError('could not remove screen recording from device');
520+
}
521+
});
522+
}
523+
450524
await step('Killing logcat process...', () async {
451525
final bool delivered = logcatProcess.kill(ProcessSignal.sigkill);
452526
assert(delivered);
@@ -536,6 +610,8 @@ Future<void> _run({
536610
}
537611
}
538612

613+
const String _emulatorStoragePath = '/storage/emulated/0/Download';
614+
539615
void _withTemporaryCwd(String path, void Function() callback) {
540616
final String originalCwd = Directory.current.path;
541617
Directory.current = Directory(path).path;

testing/scenario_app/bin/utils/options.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ extension type const Options._(ArgResults _args) {
165165
defaultsTo: environment.isCi,
166166
hide: hideUnusualOptions,
167167
)
168+
..addFlag(
169+
'record-screen',
170+
help: 'Whether to record the screen during the test run.',
171+
defaultsTo: environment.isCi,
172+
)
168173
..addOption(
169174
'impeller-backend',
170175
help: 'The graphics backend to use when --enable-impeller is true. '
@@ -286,6 +291,9 @@ extension type const Options._(ArgResults _args) {
286291
/// Whether to enable Impeller as the graphics backend.
287292
bool get enableImpeller => _args['enable-impeller'] as bool;
288293

294+
/// Whether to record the screen during the test run.
295+
bool get recordScreen => _args['record-screen'] as bool;
296+
289297
/// The graphics backend to use when --enable-impeller is true.
290298
String get impellerBackend => _args['impeller-backend'] as String;
291299

0 commit comments

Comments
 (0)