diff --git a/.ci.yaml b/.ci.yaml index a750ba905c..5405ed69e9 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -2309,6 +2309,17 @@ targets: ["devicelab", "android", "linux", "samsung", "s10"] task_name: new_gallery_impeller__transition_perf + - name: Linux_samsung_s10 new_gallery_opengles_impeller__transition_perf + bringup: true + recipe: devicelab/devicelab_drone + presubmit: false + timeout: 60 + properties: + ignore_flakiness: "true" + tags: > + ["devicelab", "android", "linux", "samsung", "s10"] + task_name: new_gallery_opengles_impeller__transition_perf + - name: Linux_android picture_cache_perf__e2e_summary recipe: devicelab/devicelab_drone presubmit: false diff --git a/TESTOWNERS b/TESTOWNERS index 8f0be05514..79d161f98c 100644 --- a/TESTOWNERS +++ b/TESTOWNERS @@ -137,6 +137,7 @@ /dev/devicelab/bin/tasks/microbenchmarks.dart @zanderso @flutter/engine /dev/devicelab/bin/tasks/new_gallery__transition_perf.dart @zanderso @flutter/engine /dev/devicelab/bin/tasks/new_gallery_impeller__transition_perf.dart @zanderso @flutter/engine +/dev/devicelab/bin/tasks/new_gallery_opengles_impeller__transition_perf.dart @gaaclarke @flutter/engine /dev/devicelab/bin/tasks/picture_cache_perf__timeline_summary.dart @zanderso @flutter/engine /dev/devicelab/bin/tasks/platform_channel_sample_test.dart @zanderso @flutter/engine /dev/devicelab/bin/tasks/platform_interaction_test.dart @stuartmorgan @flutter/plugin diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index 892a662a87..d3c6bfcbf1 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -46,6 +46,7 @@ dependencies: mime: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" node_preamble: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" package_config: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + petitparser: 5.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pool: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pub_semver: 2.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pubspec_parse: 1.2.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -68,9 +69,10 @@ dependencies: web: 0.1.4-beta # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + xml: 6.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: test_api: 0.6.1 -# PUBSPEC CHECKSUM: e586 +# PUBSPEC CHECKSUM: 7431 diff --git a/dev/devicelab/bin/tasks/new_gallery_opengles_impeller__transition_perf.dart b/dev/devicelab/bin/tasks/new_gallery_opengles_impeller__transition_perf.dart new file mode 100644 index 0000000000..2a33ce72a8 --- /dev/null +++ b/dev/devicelab/bin/tasks/new_gallery_opengles_impeller__transition_perf.dart @@ -0,0 +1,24 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:flutter_devicelab/framework/devices.dart'; +import 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/framework/utils.dart'; +import 'package:flutter_devicelab/tasks/new_gallery.dart'; +import 'package:path/path.dart' as path; + +Future main() async { + deviceOperatingSystem = DeviceOperatingSystem.android; + + final Directory galleryParentDir = Directory.systemTemp.createTempSync('flutter_new_gallery_test.'); + final Directory galleryDir = Directory(path.join(galleryParentDir.path, 'gallery')); + + try { + await task(NewGalleryPerfTest(galleryDir, enableImpeller: true, forceOpenGLES: true).run); + } finally { + rmTree(galleryParentDir); + } +} diff --git a/dev/devicelab/lib/tasks/new_gallery.dart b/dev/devicelab/lib/tasks/new_gallery.dart index dcc52ff56a..6f8b998b4b 100644 --- a/dev/devicelab/lib/tasks/new_gallery.dart +++ b/dev/devicelab/lib/tasks/new_gallery.dart @@ -16,6 +16,7 @@ class NewGalleryPerfTest extends PerfTest { String dartDefine = '', super.enableImpeller, super.timeoutSeconds, + super.forceOpenGLES, }) : super( galleryDir.path, 'test_driver/transitions_perf.dart', diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart index 0f018ad7ac..2d36b93615 100644 --- a/dev/devicelab/lib/tasks/perf_tests.dart +++ b/dev/devicelab/lib/tasks/perf_tests.dart @@ -9,6 +9,7 @@ import 'dart:math' as math; import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; +import 'package:xml/xml.dart'; import '../framework/devices.dart'; import '../framework/framework.dart'; @@ -691,6 +692,63 @@ Map _average(List> results, int iterations return tally; } +/// Opens the file at testDirectory + 'android/app/src/main/AndroidManifest.xml' +/// and adds the following entry to the application. +/// +void _addOpenGLESToManifest(String testDirectory) { + final String manifestPath = path.join( + testDirectory, 'android', 'app', 'src', 'main', 'AndroidManifest.xml'); + final File file = File(manifestPath); + + if (!file.existsSync()) { + throw Exception('AndroidManifest.xml not found at $manifestPath'); + } + + final String xmlStr = file.readAsStringSync(); + final XmlDocument xmlDoc = XmlDocument.parse(xmlStr); + const String key = 'io.flutter.embedding.android.ImpellerBackend'; + const String value = 'opengles'; + + final XmlElement applicationNode = + xmlDoc.findAllElements('application').first; + + // Check if the meta-data node already exists. + final Iterable existingMetaData = applicationNode + .findAllElements('meta-data') + .where((XmlElement node) => node.getAttribute('android:name') == key); + + if (existingMetaData.isNotEmpty) { + final XmlElement existingEntry = existingMetaData.first; + existingEntry.setAttribute('android:value', value); + } else { + final XmlElement metaData = XmlElement( + XmlName('meta-data'), + [ + XmlAttribute(XmlName('android:name'), key), + XmlAttribute(XmlName('android:value'), value) + ], + ); + + applicationNode.children.add(metaData); + } + + file.writeAsStringSync(xmlDoc.toXmlString(pretty: true, indent: ' ')); +} + +Future _resetManifest(String testDirectory) async { + final String manifestPath = path.join( + testDirectory, 'android', 'app', 'src', 'main', 'AndroidManifest.xml'); + final File file = File(manifestPath); + + if (!file.existsSync()) { + throw Exception('AndroidManifest.xml not found at $manifestPath'); + } + + await exec('git', ['checkout', file.path]); +} + /// Measure application startup performance. class StartupTest { const StartupTest(this.testDirectory, { this.reportMetrics = true, this.target = 'lib/main.dart' }); @@ -978,6 +1036,7 @@ class PerfTest { this.flutterDriveCallback, this.timeoutSeconds, this.enableImpeller, + this.forceOpenGLES, }): _resultFilename = resultFilename; const PerfTest.e2e( @@ -995,6 +1054,7 @@ class PerfTest { this.flutterDriveCallback, this.timeoutSeconds, this.enableImpeller, + this.forceOpenGLES, }) : saveTraceFile = false, timelineFileName = null, _resultFilename = resultFilename; /// The directory where the app under test is defined. @@ -1031,6 +1091,9 @@ class PerfTest { /// Whether the perf test should enable Impeller. final bool? enableImpeller; + /// Whether the perf test force Impeller's OpenGLES backend. + final bool? forceOpenGLES; + /// Number of seconds to time out the test after, allowing debug callbacks to run. final int? timeoutSeconds; @@ -1079,40 +1142,55 @@ class PerfTest { final String? localEngine = localEngineFromEnv; final String? localEngineSrcPath = localEngineSrcPathFromEnv; - final List options = [ - if (localEngine != null) - ...['--local-engine', localEngine], - if (localEngineSrcPath != null) - ...['--local-engine-src-path', localEngineSrcPath], - '--no-dds', - '--no-android-gradle-daemon', - '-v', - '--verbose-system-logs', - '--profile', - if (timeoutSeconds != null) - ...[ + Future Function()? manifestReset; + if (forceOpenGLES ?? false) { + assert(enableImpeller!); + _addOpenGLESToManifest(testDirectory); + manifestReset = () => _resetManifest(testDirectory); + } + + try { + final List options = [ + if (localEngine != null) ...['--local-engine', localEngine], + if (localEngineSrcPath != null) ...[ + '--local-engine-src-path', + localEngineSrcPath + ], + '--no-dds', + '--no-android-gradle-daemon', + '-v', + '--verbose-system-logs', + '--profile', + if (timeoutSeconds != null) ...[ '--timeout', timeoutSeconds.toString(), ], - if (needsFullTimeline) - '--trace-startup', // Enables "endless" timeline event buffering. - '-t', testTarget, - if (testDriver != null) - ...['--driver', testDriver!], - if (existingApp != null) - ...['--use-existing-app', existingApp], - if (dartDefine.isNotEmpty) - ...['--dart-define', dartDefine], - if (enableImpeller != null && enableImpeller!) '--enable-impeller', - if (enableImpeller != null && !enableImpeller!) '--no-enable-impeller', - '-d', - deviceId, - ]; - if (flutterDriveCallback != null) { - flutterDriveCallback!(options); - } else { - await flutter('drive', options: options); + if (needsFullTimeline) + '--trace-startup', // Enables "endless" timeline event buffering. + '-t', testTarget, + if (testDriver != null) ...['--driver', testDriver!], + if (existingApp != null) ...[ + '--use-existing-app', + existingApp + ], + if (dartDefine.isNotEmpty) ...['--dart-define', dartDefine], + if (enableImpeller != null && enableImpeller!) '--enable-impeller', + if (enableImpeller != null && !enableImpeller!) + '--no-enable-impeller', + '-d', + deviceId, + ]; + if (flutterDriveCallback != null) { + flutterDriveCallback!(options); + } else { + await flutter('drive', options: options); + } + } finally { + if (manifestReset != null) { + await manifestReset(); + } } + final Map data = json.decode( file('${_testOutputDirectory(testDirectory)}/$resultFilename.json').readAsStringSync(), ) as Map; diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml index e9a76d4aa9..5c76b6c12d 100644 --- a/dev/devicelab/pubspec.yaml +++ b/dev/devicelab/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: vm_service: 11.8.0 web: 0.1.4-beta webkit_inspection_protocol: 1.2.0 + xml: 6.3.0 _discoveryapis_commons: 1.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -37,6 +38,7 @@ dependencies: js: 0.6.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" json_annotation: 4.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" mime: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + petitparser: 5.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" pub_semver: 2.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" retry: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" source_span: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -71,4 +73,4 @@ dev_dependencies: watcher: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: a9f3 +# PUBSPEC CHECKSUM: 289e