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

Commit 0370314

Browse files
authored
Revert "Re-enable scenario tests on Android (#33574)"
This reverts commit ada245a.
1 parent 9e0316d commit 0370314

File tree

58 files changed

+329
-722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+329
-722
lines changed

.ci.yaml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,16 @@ targets:
100100
timeout: 60
101101

102102
- name: Linux Android Emulator Tests
103+
bringup: true # Recipe issue https://github.com/flutter/flutter/issues/86427
103104
recipe: engine/scenarios
104-
enabled_branches:
105-
- main
106-
- master
107105
properties:
108106
dependencies: >-
109107
[
110-
{"dependency": "android_virtual_device", "version": "31"},
111-
{"dependency": "goldctl"}
108+
{"dependency": "android_virtual_device", "version": "31"}
112109
]
113110
upload_packages: "true"
114111
clobber: "true"
115112
timeout: 60
116-
runIf:
117-
- DEPS
118-
- .ci.yaml
119-
- testing/**
120-
- shell/platforms/android/**
121113

122114
- name: Linux Benchmarks
123115
enabled_branches:

shell/platform/android/android_context_gl_unittests.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ TEST(AndroidSurfaceGL, CreateSnapshopSurfaceWhenOnscreenSurfaceIsNull) {
164164
EXPECT_NE(android_surface->GetOnscreenSurface(), nullptr);
165165
}
166166

167-
// TODO(https://github.com/flutter/flutter/issues/104463): Flaky test.
168-
TEST(AndroidContextGl, DISABLED_MSAAx4) {
167+
TEST(AndroidContextGl, MSAAx4) {
169168
GrMockOptions main_context_options;
170169
sk_sp<GrDirectContext> main_context =
171170
GrDirectContext::MakeMock(&main_context_options);

shell/platform/android/external_view_embedder/external_view_embedder.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,6 @@ void AndroidExternalViewEmbedder::SubmitFrame(
9898

9999
for (size_t i = 0; i < current_frame_view_count; i++) {
100100
int64_t view_id = composition_order_[i];
101-
if (picture_recorders_.at(view_id)->getRecordingCanvas() == nullptr) {
102-
continue;
103-
}
104101

105102
sk_sp<SkPicture> picture =
106103
picture_recorders_.at(view_id)->finishRecordingAsPicture();

testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/ScreenshotUtil.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ private static class Connection {
3737
}
3838

3939
synchronized void writeFile(String name, byte[] fileContent) throws IOException {
40-
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + fileContent.length + 8);
41-
// See ScreenshotBlobTransformer#bind in screenshot_transformer.dart for consumer side.
40+
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + fileContent.length + 4);
4241
buffer.putInt(name.length());
43-
buffer.putInt(fileContent.length);
4442
buffer.put(name.getBytes());
4543
buffer.put(fileContent);
4644
final byte[] bytes = buffer.array();
@@ -120,9 +118,6 @@ public static void capture(@NonNull TestableFlutterActivity activity, @NonNull S
120118

121119
final Bitmap bitmap =
122120
InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
123-
if (bitmap == null) {
124-
throw new RuntimeException("failed to capture screenshot");
125-
}
126121
final ByteArrayOutputStream out = new ByteArrayOutputStream();
127122
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
128123
ScreenshotUtil.writeFile(captureName, out.toByteArray());

testing/scenario_app/android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
android:hardwareAccelerated="true"
1515
android:launchMode="singleTop"
1616
android:windowSoftInputMode="adjustResize"
17+
android:theme="@style/FullScreenScreenshot"
1718
android:exported="true">
1819
<intent-filter>
1920
<action android:name="com.google.intent.action.TEST_LOOP" />
@@ -31,6 +32,7 @@
3132
android:hardwareAccelerated="true"
3233
android:launchMode="singleTop"
3334
android:windowSoftInputMode="adjustResize"
35+
android:theme="@style/FullScreenScreenshot"
3436
android:exported="true">
3537
<intent-filter>
3638
<action android:name="android.intent.action.MAIN" />
@@ -43,6 +45,7 @@
4345
android:hardwareAccelerated="true"
4446
android:launchMode="singleTop"
4547
android:windowSoftInputMode="adjustResize"
48+
android:theme="@style/FullScreenScreenshot"
4649
android:exported="true">
4750
<intent-filter>
4851
<action android:name="android.intent.action.MAIN" />

testing/scenario_app/android/app/src/main/java/dev/flutter/scenarios/TestActivity.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@
1212
import android.os.Bundle;
1313
import android.os.Handler;
1414
import android.os.Looper;
15-
import android.view.Window;
1615
import androidx.annotation.NonNull;
1716
import androidx.annotation.Nullable;
18-
import androidx.core.view.WindowCompat;
19-
import androidx.core.view.WindowInsetsCompat;
20-
import androidx.core.view.WindowInsetsControllerCompat;
2117
import io.flutter.Log;
2218
import io.flutter.embedding.engine.FlutterShellArgs;
2319
import io.flutter.embedding.engine.loader.FlutterLoader;
@@ -39,8 +35,6 @@ public abstract class TestActivity extends TestableFlutterActivity {
3935
@Override
4036
protected void onCreate(@Nullable Bundle savedInstanceState) {
4137
super.onCreate(savedInstanceState);
42-
hideSystemBars(getWindow());
43-
4438
final Intent launchIntent = getIntent();
4539
if ("com.google.intent.action.TEST_LOOP".equals(launchIntent.getAction())) {
4640
if (Build.VERSION.SDK_INT > 22) {
@@ -164,12 +158,4 @@ public void run() {
164158
}
165159
});
166160
}
167-
168-
private static void hideSystemBars(Window window) {
169-
final WindowInsetsControllerCompat insetController =
170-
WindowCompat.getInsetsController(window, window.getDecorView());
171-
insetController.setSystemBarsBehavior(
172-
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
173-
insetController.hide(WindowInsetsCompat.Type.systemBars());
174-
}
175161
}

testing/scenario_app/android/app/src/main/res/values/styles.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,11 @@
88
<item name="colorAccent">@color/colorAccent</item>
99
</style>
1010

11+
<style name="FullScreenScreenshot">
12+
<item name="android:windowNoTitle">true</item>
13+
<item name="android:windowActionBar">false</item>
14+
<item name="android:windowFullscreen">true</item>
15+
<item name="android:windowContentOverlay">@null</item>
16+
</style>
17+
1118
</resources>

testing/scenario_app/bin/android_integration_tests.dart

Lines changed: 15 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// found in the LICENSE file.
44

55
import 'dart:async';
6+
import 'dart:convert';
67
import 'dart:io';
78
import 'dart:typed_data';
89

910
import 'package:args/args.dart';
1011
import 'package:path/path.dart';
1112
import 'package:process/process.dart';
12-
import 'package:skia_gold_client/skia_gold_client.dart';
1313

1414
import 'utils/logs.dart';
1515
import 'utils/process_manager_extension.dart';
16-
import 'utils/screenshot_transformer.dart';
1716

1817
const int tcpPort = 3001;
1918

@@ -35,12 +34,9 @@ void main(List<String> args) async {
3534
panic(<String>['cannot find adb: $adb', 'make sure to run gclient sync']);
3635
}
3736

38-
final String scenarioAppPath = join(outDir.path, 'scenario_app');
39-
final String logcatPath = join(scenarioAppPath, 'logcat.txt');
40-
final String screenshotPath = join(scenarioAppPath, 'screenshots');
41-
final String apkOutPath = join(scenarioAppPath, 'app', 'outputs', 'apk');
42-
final File testApk = File(join(apkOutPath, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
43-
final File appApk = File(join(apkOutPath, 'debug', 'app-debug.apk'));
37+
final String apkOut = join(outDir.path, 'scenario_app', 'app', 'outputs', 'apk');
38+
final File testApk = File(join(apkOut, 'androidTest', 'debug', 'app-debug-androidTest.apk'));
39+
final File appApk = File(join(apkOut, 'debug', 'app-debug.apk'));
4440

4541
if (!testApk.existsSync()) {
4642
panic(<String>['test apk does not exist: ${testApk.path}', 'make sure to build the selected engine variant']);
@@ -54,97 +50,30 @@ void main(List<String> args) async {
5450
// This allows the test process to start a connection with the host, and write the bytes
5551
// for the screenshots.
5652
// On LUCI, the host uploads the screenshots to Skia Gold.
57-
SkiaGoldClient? skiaGoldClient;
5853
late ServerSocket server;
59-
final List<Future<void>> pendingComparisons = <Future<void>>[];
6054
await step('Starting server...', () async {
6155
server = await ServerSocket.bind(InternetAddress.anyIPv4, tcpPort);
6256
stdout.writeln('listening on host ${server.address.address}:${server.port}');
6357
server.listen((Socket client) {
6458
stdout.writeln('client connected ${client.remoteAddress.address}:${client.remotePort}');
65-
client.transform(const ScreenshotBlobTransformer()).listen((Screenshot screenshot) {
66-
final String fileName = screenshot.filename;
67-
final Uint8List fileContent = screenshot.fileContent;
59+
60+
client.listen((Uint8List data) {
61+
final int fnameLen = data.buffer.asByteData().getInt32(0);
62+
final String fileName = utf8.decode(data.buffer.asUint8List(4, fnameLen));
63+
final Uint8List fileContent = data.buffer.asUint8List(4 + fnameLen);
6864
log('host received ${fileContent.lengthInBytes} bytes for screenshot `$fileName`');
69-
assert(skiaGoldClient != null, 'expected Skia Gold client');
70-
late File goldenFile;
71-
try {
72-
goldenFile = File(join(screenshotPath, fileName))..writeAsBytesSync(fileContent, flush: true);
73-
} on FileSystemException catch (err) {
74-
panic(<String>['failed to create screenshot $fileName: ${err.toString()}']);
75-
}
76-
log('wrote ${goldenFile.absolute.path}');
77-
if (isSkiaGoldClientAvailable) {
78-
final Future<void> comparison = skiaGoldClient!
79-
.addImg(fileName, goldenFile, screenshotSize: fileContent.lengthInBytes)
80-
.catchError((dynamic err) {
81-
panic(<String>['skia gold comparison failed: ${err.toString()}']);
82-
});
83-
pendingComparisons.add(comparison);
84-
}
85-
},
86-
onError: (dynamic err) {
87-
panic(<String>['error while receiving bytes: ${err.toString()}']);
88-
},
89-
cancelOnError: true);
65+
});
9066
});
9167
});
9268

9369
late Process logcatProcess;
94-
final IOSink logcat = File(logcatPath).openWrite();
70+
final StringBuffer logcat = StringBuffer();
9571
try {
96-
await step('Creating screenshot directory...', () async {
97-
Directory(screenshotPath).createSync(recursive: true);
98-
});
99-
10072
await step('Starting logcat...', () async {
101-
final int exitCode = await pm.runAndForward(<String>[adb.path, 'logcat', '-c']);
102-
if (exitCode != 0) {
103-
panic(<String>['could not clear logs']);
104-
}
105-
logcatProcess = await pm.start(<String>[adb.path, 'logcat', '-T', '1']);
73+
logcatProcess = await pm.start(<String>[adb.path, 'logcat', '*:E', '-T', '1']);
10674
unawaited(pipeProcessStreams(logcatProcess, out: logcat));
10775
});
10876

109-
await step('Configuring emulator...', () async {
110-
final int exitCode = await pm.runAndForward(<String>[
111-
adb.path,
112-
'shell',
113-
'settings',
114-
'put',
115-
'secure',
116-
'immersive_mode_confirmations',
117-
'confirmed',
118-
]);
119-
if (exitCode != 0) {
120-
panic(<String>['could not configure emulator']);
121-
}
122-
});
123-
124-
await step('Get API level of connected device...', () async {
125-
final ProcessResult apiLevelProcessResult = await pm.run(<String>[adb.path, 'shell', 'getprop', 'ro.build.version.sdk']);
126-
if (apiLevelProcessResult.exitCode != 0) {
127-
panic(<String>['could not get API level of the connected device']);
128-
}
129-
final String connectedDeviceAPILevel = (apiLevelProcessResult.stdout as String).trim();
130-
log('using API level $connectedDeviceAPILevel');
131-
skiaGoldClient = SkiaGoldClient(
132-
outDir,
133-
dimensions: <String, String>{
134-
'AndroidAPILevel': connectedDeviceAPILevel,
135-
},
136-
);
137-
});
138-
139-
await step('Skia Gold auth...', () async {
140-
if (isSkiaGoldClientAvailable) {
141-
await skiaGoldClient!.auth();
142-
log('skia gold client is available');
143-
} else {
144-
log('skia gold client is unavailable');
145-
}
146-
});
147-
14877
await step('Reverse port...', () async {
14978
final int exitCode = await pm.runAndForward(<String>[adb.path, 'reverse', 'tcp:3000', 'tcp:$tcpPort']);
15079
if (exitCode != 0) {
@@ -207,18 +136,11 @@ void main(List<String> args) async {
207136
});
208137

209138
await step('Killing logcat process...', () async {
210-
final bool delivered = logcatProcess.kill(ProcessSignal.sigkill);
211-
assert(delivered);
139+
logcatProcess.kill();
212140
});
213141

214-
await step('Wait for Skia gold comparisons...', () async {
215-
await Future.wait(pendingComparisons);
142+
await step('Dumping logcat (Errors only)...', () async {
143+
stdout.write(logcat);
216144
});
217-
218-
await step('Flush logcat...', () async {
219-
await logcat.flush();
220-
});
221-
222-
exit(0);
223145
}
224146
}

testing/scenario_app/bin/utils/process_manager_extension.dart

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,31 @@ import 'dart:io';
88

99
import 'package:process/process.dart';
1010

11-
/// Pipes the [process] streams and writes them to [out] sink.
12-
/// If [out] is null, then the current [Process.stdout] is used as the sink.
13-
/// If [includePrefix] is true, then the prefix `[stdout]` or `[stderr]` is
14-
/// added before writting to the [out] sink.
15-
Future<int> pipeProcessStreams(
16-
Process process, {
17-
StringSink? out,
18-
bool includePrefix = true,
19-
}) async {
11+
/// Pipes the [process] streams and writes them to [out].
12+
Future<int> pipeProcessStreams(Process process, {StringSink? out}) async {
2013
out ??= stdout;
2114
final Completer<void> stdoutCompleter = Completer<void>();
2215
final StreamSubscription<String> stdoutSub = process.stdout
2316
.transform(utf8.decoder)
2417
.transform<String>(const LineSplitter())
2518
.listen((String line) {
26-
if (includePrefix) {
27-
out!.writeln('[stdout] $line');
28-
} else {
29-
out!.writeln(line);
30-
}
19+
out!.writeln('[stdout] $line');
3120
}, onDone: stdoutCompleter.complete);
3221

3322
final Completer<void> stderrCompleter = Completer<void>();
3423
final StreamSubscription<String> stderrSub = process.stderr
3524
.transform(utf8.decoder)
3625
.transform<String>(const LineSplitter())
3726
.listen((String line) {
38-
if (includePrefix) {
39-
out!.writeln('[stderr] $line');
40-
} else {
41-
out!.writeln(line);
42-
}
27+
out!.writeln('[stderr] $line');
4328
}, onDone: stderrCompleter.complete);
4429

4530
final int exitCode = await process.exitCode;
46-
await stderrSub.cancel();
47-
await stdoutSub.cancel();
48-
4931
await stdoutCompleter.future;
5032
await stderrCompleter.future;
33+
34+
stderrSub.cancel();
35+
stdoutSub.cancel();
5136
return exitCode;
5237
}
5338

0 commit comments

Comments
 (0)