Skip to content

Commit 6c818d7

Browse files
author
Emmanuel Garcia
authored
Add Android lifecycles test (#99319)
1 parent 64d9ea6 commit 6c818d7

File tree

6 files changed

+289
-57
lines changed

6 files changed

+289
-57
lines changed

.ci.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,17 @@ targets:
23882388
task_name: android_choreographer_do_frame_test
23892389
scheduler: luci
23902390

2391+
- name: Linux_android android_lifecycles_test
2392+
bringup: true
2393+
recipe: devicelab/devicelab_drone
2394+
presubmit: false
2395+
timeout: 60
2396+
properties:
2397+
tags: >
2398+
["devicelab","android","linux"]
2399+
task_name: android_lifecycles_test
2400+
scheduler: luci
2401+
23912402
- name: Mac build_aar_module_test
23922403
recipe: devicelab/devicelab_drone
23932404
timeout: 60

TESTOWNERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
## Linux Android DeviceLab tests
1212
/dev/devicelab/bin/tasks/analyzer_benchmark.dart @zanderso @flutter/tool
13+
/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart @blasten @flutter/engine
1314
/dev/devicelab/bin/tasks/android_defines_test.dart @zanderso @flutter/tool
15+
/dev/devicelab/bin/tasks/android_lifecycles_test.dart @blasten @flutter/engine
1416
/dev/devicelab/bin/tasks/android_obfuscate_test.dart @zanderso @flutter/tool
1517
/dev/devicelab/bin/tasks/android_picture_cache_complexity_scoring_perf__timeline_summary.dart @flar @flutter/engine
1618
/dev/devicelab/bin/tasks/android_stack_size_test.dart @zanderso @flutter/tool
@@ -71,7 +73,6 @@
7173
/dev/devicelab/bin/tasks/opacity_peephole_fade_transition_text_perf__e2e_summary.dart @flar @flutter/engine
7274
/dev/devicelab/bin/tasks/opacity_peephole_col_of_alpha_savelayer_rows_perf__e2e_summary.dart @flar @flutter/engine
7375
/dev/devicelab/bin/tasks/opacity_peephole_grid_of_alpha_savelayers_perf__e2e_summary.dart @flar @flutter/engine
74-
/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart @blasten @flutter/engine
7576

7677
## Windows Android DeviceLab tests
7778
/dev/devicelab/bin/tasks/basic_material_app_win__compile.dart @zanderso @flutter/tool
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter_devicelab/framework/framework.dart';
6+
import 'package:flutter_devicelab/tasks/android_lifecycles_test.dart';
7+
8+
Future<void> main() async {
9+
await task(androidLifecyclesTest());
10+
}

dev/devicelab/lib/framework/devices.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ class AndroidDevice extends Device {
545545
}
546546
}
547547

548-
/// Executes [command] on `adb shell` and returns its exit code.
548+
/// Executes [command] on `adb shell`.
549549
Future<void> shellExec(String command, List<String> arguments, { Map<String, String>? environment, bool silent = false }) async {
550550
await adb(<String>['shell', command, ...arguments], environment: environment, silent: silent);
551551
}
@@ -637,7 +637,7 @@ class AndroidDevice extends Device {
637637
late final StreamController<String> stream;
638638
stream = StreamController<String>(
639639
onListen: () async {
640-
await adb(<String>['logcat', '--clear']);
640+
await adb(<String>['logcat', '-c']);
641641
final Process process = await startProcess(
642642
adbPath,
643643
// Make logcat less chatty by filtering down to just ActivityManager

dev/devicelab/lib/tasks/android_choreographer_do_frame_test.dart

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@ const List<String> kSentinelStr = <String>[
1818
'==== sentinel #3 ====',
1919
];
2020

21-
// Regression test for https://github.com/flutter/flutter/issues/98973
22-
// This test ensures that Choreographer#doFrame finishes during application startup.
23-
// This test fails if the application hangs during this period.
24-
// https://ui.perfetto.dev/#!/?s=da6628c3a92456ae8fa3f345d0186e781da77e90fc8a64d073e9fee11d1e65
21+
/// Tests that Choreographer#doFrame finishes during application startup.
22+
/// This test fails if the application hangs during this period.
23+
/// https://ui.perfetto.dev/#!/?s=da6628c3a92456ae8fa3f345d0186e781da77e90fc8a64d073e9fee11d1e65
24+
/// Regression test for https://github.com/flutter/flutter/issues/98973
2525
TaskFunction androidChoreographerDoFrameTest({
26-
String? deviceIdOverride,
2726
Map<String, String>? environment,
2827
}) {
2928
final Directory tempDir = Directory.systemTemp
@@ -87,18 +86,19 @@ Future<void> main() async {
8786
}
8887

8988
section('Flutter run (mode: $mode)');
89+
late Process run;
9090
await inDirectory(path.join(tempDir.path, 'app'), () async {
91-
final Process run = await startProcess(
91+
run = await startProcess(
9292
path.join(flutterDirectory.path, 'bin', 'flutter'),
9393
flutterCommandArgs('run', <String>['--$mode', '--verbose']),
9494
);
95+
});
9596

96-
int currSentinelIdx = 0;
97-
final StreamSubscription<void> stdout = run.stdout
98-
.transform<String>(utf8.decoder)
99-
.transform<String>(const LineSplitter())
100-
.listen((String line) {
101-
97+
int currSentinelIdx = 0;
98+
final StreamSubscription<void> stdout = run.stdout
99+
.transform<String>(utf8.decoder)
100+
.transform<String>(const LineSplitter())
101+
.listen((String line) {
102102
if (currSentinelIdx < sentinelCompleters.keys.length &&
103103
line.contains(sentinelCompleters.keys.elementAt(currSentinelIdx))) {
104104
sentinelCompleters.values.elementAt(currSentinelIdx).complete();
@@ -107,61 +107,59 @@ Future<void> main() async {
107107
} else {
108108
print('stdout: $line');
109109
}
110-
111110
});
112111

113-
final StreamSubscription<void> stderr = run.stderr
114-
.transform<String>(utf8.decoder)
115-
.transform<String>(const LineSplitter())
116-
.listen((String line) {
117-
print('stderr: $line');
118-
});
119-
120-
final Completer<void> exitCompleter = Completer<void>();
121-
122-
unawaited(run.exitCode.then((int exitCode) {
123-
exitCompleter.complete();
124-
}));
112+
final StreamSubscription<void> stderr = run.stderr
113+
.transform<String>(utf8.decoder)
114+
.transform<String>(const LineSplitter())
115+
.listen((String line) {
116+
print('stderr: $line');
117+
});
125118

126-
section('Wait for sentinels (mode: $mode)');
127-
for (final Completer<void> completer in sentinelCompleters.values) {
128-
if (nextCompleterIdx == 0) {
129-
// Don't time out because we don't know how long it would take to get the first log.
119+
final Completer<void> exitCompleter = Completer<void>();
120+
121+
unawaited(run.exitCode.then((int exitCode) {
122+
exitCompleter.complete();
123+
}));
124+
125+
section('Wait for sentinels (mode: $mode)');
126+
for (final Completer<void> completer in sentinelCompleters.values) {
127+
if (nextCompleterIdx == 0) {
128+
// Don't time out because we don't know how long it would take to get the first log.
129+
await Future.any<dynamic>(
130+
<Future<dynamic>>[
131+
completer.future,
132+
exitCompleter.future,
133+
],
134+
);
135+
} else {
136+
try {
137+
// Time out since this should not take 1s after the first log was received.
130138
await Future.any<dynamic>(
131139
<Future<dynamic>>[
132-
completer.future,
140+
completer.future.timeout(const Duration(seconds: 1)),
133141
exitCompleter.future,
134142
],
135143
);
136-
} else {
137-
try {
138-
// Time out since this should not take 1s after the first log was received.
139-
await Future.any<dynamic>(
140-
<Future<dynamic>>[
141-
completer.future.timeout(const Duration(seconds: 1)),
142-
exitCompleter.future,
143-
],
144-
);
145-
} on TimeoutException {
146-
break;
147-
}
148-
}
149-
if (exitCompleter.isCompleted) {
150-
// The process exited.
144+
} on TimeoutException {
151145
break;
152146
}
153-
nextCompleterIdx++;
154147
}
148+
if (exitCompleter.isCompleted) {
149+
// The process exited.
150+
break;
151+
}
152+
nextCompleterIdx++;
153+
}
155154

156-
section('Quit app (mode: $mode)');
157-
run.stdin.write('q');
158-
await exitCompleter.future;
155+
section('Quit app (mode: $mode)');
156+
run.stdin.write('q');
157+
await exitCompleter.future;
159158

160-
section('Stop listening to stdout and stderr (mode: $mode)');
161-
await stdout.cancel();
162-
await stderr.cancel();
163-
run.kill();
164-
});
159+
section('Stop listening to stdout and stderr (mode: $mode)');
160+
await stdout.cancel();
161+
await stderr.cancel();
162+
run.kill();
165163

166164
if (nextCompleterIdx == sentinelCompleters.values.length) {
167165
return TaskResult.success(null);

0 commit comments

Comments
 (0)