@@ -9,6 +9,7 @@ import 'dart:math' as math;
9
9
10
10
import 'package:meta/meta.dart' ;
11
11
import 'package:path/path.dart' as path;
12
+ import 'package:xml/xml.dart' ;
12
13
13
14
import '../framework/devices.dart' ;
14
15
import '../framework/framework.dart' ;
@@ -691,6 +692,63 @@ Map<String, dynamic> _average(List<Map<String, dynamic>> results, int iterations
691
692
return tally;
692
693
}
693
694
695
+ /// Opens the file at testDirectory + 'android/app/src/main/AndroidManifest.xml'
696
+ /// and adds the following entry to the application.
697
+ /// <meta-data
698
+ /// android:name="io.flutter.embedding.android.ImpellerBackend"
699
+ /// android:value="opengles" />
700
+ void _addOpenGLESToManifest (String testDirectory) {
701
+ final String manifestPath = path.join (
702
+ testDirectory, 'android' , 'app' , 'src' , 'main' , 'AndroidManifest.xml' );
703
+ final File file = File (manifestPath);
704
+
705
+ if (! file.existsSync ()) {
706
+ throw Exception ('AndroidManifest.xml not found at $manifestPath ' );
707
+ }
708
+
709
+ final String xmlStr = file.readAsStringSync ();
710
+ final XmlDocument xmlDoc = XmlDocument .parse (xmlStr);
711
+ const String key = 'io.flutter.embedding.android.ImpellerBackend' ;
712
+ const String value = 'opengles' ;
713
+
714
+ final XmlElement applicationNode =
715
+ xmlDoc.findAllElements ('application' ).first;
716
+
717
+ // Check if the meta-data node already exists.
718
+ final Iterable <XmlElement > existingMetaData = applicationNode
719
+ .findAllElements ('meta-data' )
720
+ .where ((XmlElement node) => node.getAttribute ('android:name' ) == key);
721
+
722
+ if (existingMetaData.isNotEmpty) {
723
+ final XmlElement existingEntry = existingMetaData.first;
724
+ existingEntry.setAttribute ('android:value' , value);
725
+ } else {
726
+ final XmlElement metaData = XmlElement (
727
+ XmlName ('meta-data' ),
728
+ < XmlAttribute > [
729
+ XmlAttribute (XmlName ('android:name' ), key),
730
+ XmlAttribute (XmlName ('android:value' ), value)
731
+ ],
732
+ );
733
+
734
+ applicationNode.children.add (metaData);
735
+ }
736
+
737
+ file.writeAsStringSync (xmlDoc.toXmlString (pretty: true , indent: ' ' ));
738
+ }
739
+
740
+ Future <void > _resetManifest (String testDirectory) async {
741
+ final String manifestPath = path.join (
742
+ testDirectory, 'android' , 'app' , 'src' , 'main' , 'AndroidManifest.xml' );
743
+ final File file = File (manifestPath);
744
+
745
+ if (! file.existsSync ()) {
746
+ throw Exception ('AndroidManifest.xml not found at $manifestPath ' );
747
+ }
748
+
749
+ await exec ('git' , < String > ['checkout' , file.path]);
750
+ }
751
+
694
752
/// Measure application startup performance.
695
753
class StartupTest {
696
754
const StartupTest (this .testDirectory, { this .reportMetrics = true , this .target = 'lib/main.dart' });
@@ -978,6 +1036,7 @@ class PerfTest {
978
1036
this .flutterDriveCallback,
979
1037
this .timeoutSeconds,
980
1038
this .enableImpeller,
1039
+ this .forceOpenGLES,
981
1040
}): _resultFilename = resultFilename;
982
1041
983
1042
const PerfTest .e2e (
@@ -995,6 +1054,7 @@ class PerfTest {
995
1054
this .flutterDriveCallback,
996
1055
this .timeoutSeconds,
997
1056
this .enableImpeller,
1057
+ this .forceOpenGLES,
998
1058
}) : saveTraceFile = false , timelineFileName = null , _resultFilename = resultFilename;
999
1059
1000
1060
/// The directory where the app under test is defined.
@@ -1031,6 +1091,9 @@ class PerfTest {
1031
1091
/// Whether the perf test should enable Impeller.
1032
1092
final bool ? enableImpeller;
1033
1093
1094
+ /// Whether the perf test force Impeller's OpenGLES backend.
1095
+ final bool ? forceOpenGLES;
1096
+
1034
1097
/// Number of seconds to time out the test after, allowing debug callbacks to run.
1035
1098
final int ? timeoutSeconds;
1036
1099
@@ -1079,40 +1142,55 @@ class PerfTest {
1079
1142
final String ? localEngine = localEngineFromEnv;
1080
1143
final String ? localEngineSrcPath = localEngineSrcPathFromEnv;
1081
1144
1082
- final List <String > options = < String > [
1083
- if (localEngine != null )
1084
- ...< String > ['--local-engine' , localEngine],
1085
- if (localEngineSrcPath != null )
1086
- ...< String > ['--local-engine-src-path' , localEngineSrcPath],
1087
- '--no-dds' ,
1088
- '--no-android-gradle-daemon' ,
1089
- '-v' ,
1090
- '--verbose-system-logs' ,
1091
- '--profile' ,
1092
- if (timeoutSeconds != null )
1093
- ...< String > [
1145
+ Future <void > Function ()? manifestReset;
1146
+ if (forceOpenGLES ?? false ) {
1147
+ assert (enableImpeller! );
1148
+ _addOpenGLESToManifest (testDirectory);
1149
+ manifestReset = () => _resetManifest (testDirectory);
1150
+ }
1151
+
1152
+ try {
1153
+ final List <String > options = < String > [
1154
+ if (localEngine != null ) ...< String > ['--local-engine' , localEngine],
1155
+ if (localEngineSrcPath != null ) ...< String > [
1156
+ '--local-engine-src-path' ,
1157
+ localEngineSrcPath
1158
+ ],
1159
+ '--no-dds' ,
1160
+ '--no-android-gradle-daemon' ,
1161
+ '-v' ,
1162
+ '--verbose-system-logs' ,
1163
+ '--profile' ,
1164
+ if (timeoutSeconds != null ) ...< String > [
1094
1165
'--timeout' ,
1095
1166
timeoutSeconds.toString (),
1096
1167
],
1097
- if (needsFullTimeline)
1098
- '--trace-startup' , // Enables "endless" timeline event buffering.
1099
- '-t' , testTarget,
1100
- if (testDriver != null )
1101
- ...< String > ['--driver' , testDriver! ],
1102
- if (existingApp != null )
1103
- ...< String > ['--use-existing-app' , existingApp],
1104
- if (dartDefine.isNotEmpty)
1105
- ...< String > ['--dart-define' , dartDefine],
1106
- if (enableImpeller != null && enableImpeller! ) '--enable-impeller' ,
1107
- if (enableImpeller != null && ! enableImpeller! ) '--no-enable-impeller' ,
1108
- '-d' ,
1109
- deviceId,
1110
- ];
1111
- if (flutterDriveCallback != null ) {
1112
- flutterDriveCallback !(options);
1113
- } else {
1114
- await flutter ('drive' , options: options);
1168
+ if (needsFullTimeline)
1169
+ '--trace-startup' , // Enables "endless" timeline event buffering.
1170
+ '-t' , testTarget,
1171
+ if (testDriver != null ) ...< String > ['--driver' , testDriver! ],
1172
+ if (existingApp != null ) ...< String > [
1173
+ '--use-existing-app' ,
1174
+ existingApp
1175
+ ],
1176
+ if (dartDefine.isNotEmpty) ...< String > ['--dart-define' , dartDefine],
1177
+ if (enableImpeller != null && enableImpeller! ) '--enable-impeller' ,
1178
+ if (enableImpeller != null && ! enableImpeller! )
1179
+ '--no-enable-impeller' ,
1180
+ '-d' ,
1181
+ deviceId,
1182
+ ];
1183
+ if (flutterDriveCallback != null ) {
1184
+ flutterDriveCallback !(options);
1185
+ } else {
1186
+ await flutter ('drive' , options: options);
1187
+ }
1188
+ } finally {
1189
+ if (manifestReset != null ) {
1190
+ await manifestReset ();
1191
+ }
1115
1192
}
1193
+
1116
1194
final Map <String , dynamic > data = json.decode (
1117
1195
file ('${_testOutputDirectory (testDirectory )}/$resultFilename .json' ).readAsStringSync (),
1118
1196
) as Map <String , dynamic >;
0 commit comments