// 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:async';
import 'dart:convert' show LineSplitter, json, utf8;
import 'dart:ffi' show Abi;
import 'dart:io';
import 'dart:math' as math;

import 'package:collection/collection.dart';
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';
import '../framework/host_agent.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';

/// Must match flutter_driver/lib/src/common.dart.
///
/// Redefined here to avoid taking a dependency on flutter_driver.
String testOutputDirectory(String testDirectory) {
  return Platform.environment['FLUTTER_TEST_OUTPUTS_DIR'] ?? '$testDirectory/build';
}

TaskFunction createComplexLayoutScrollPerfTest({
  bool measureCpuGpu = true,
  bool badScroll = false,
  bool? enableImpeller,
  bool forceOpenGLES = false,
}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/complex_layout',
    badScroll ? 'test_driver/scroll_perf_bad.dart' : 'test_driver/scroll_perf.dart',
    'complex_layout_scroll_perf',
    measureCpuGpu: measureCpuGpu,
    enableImpeller: enableImpeller,
    forceOpenGLES: forceOpenGLES,
  ).run;
}

TaskFunction createTilesScrollPerfTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/complex_layout',
    'test_driver/scroll_perf.dart',
    'tiles_scroll_perf',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createUiKitViewScrollPerfTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/uikit_view_scroll_perf.dart',
    'platform_views_scroll_perf',
    testDriver: 'test_driver/scroll_perf_test.dart',
    needsFullTimeline: false,
    enableImpeller: enableImpeller,
    enableMergedPlatformThread: true,
  ).run;
}

TaskFunction createUiKitViewScrollPerfAdBannersTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/uikit_view_scroll_perf_ad_banners.dart',
    'platform_views_scroll_perf_ad_banners',
    testDriver: 'test_driver/scroll_perf_ad_banners_test.dart',
    needsFullTimeline: false,
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createUiKitViewScrollPerfBottomAdBannerTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/uikit_view_scroll_perf_bottom_ad_banner.dart',
    'platform_views_scroll_perf_bottom_ad_banner',
    testDriver: 'test_driver/scroll_perf_bottom_ad_banner_test.dart',
    needsFullTimeline: false,
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createUiKitViewScrollPerfNonIntersectingTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/uikit_view_scroll_perf_non_intersecting.dart',
    'platform_views_scroll_perf_non_intersecting',
    testDriver: 'test_driver/scroll_perf_non_intersecting_test.dart',
    needsFullTimeline: false,
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createAndroidTextureScrollPerfTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/android_view_scroll_perf.dart',
    'platform_views_scroll_perf',
    testDriver: 'test_driver/scroll_perf_test.dart',
    needsFullTimeline: false,
    enableImpeller: enableImpeller,
    enableMergedPlatformThread: true,
  ).run;
}

TaskFunction createAndroidHCPPScrollPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout',
    'test_driver/scroll_perf_hcpp.dart',
    'platform_views_hcpp_scroll_perf',
    testDriver: 'test_driver/scroll_perf_hcpp_test.dart',
    needsFullTimeline: false,
    enableImpeller: true,
    enableSurfaceControl: true,
    enableMergedPlatformThread: true,
  ).run;
}

TaskFunction createAndroidViewScrollPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/platform_views_layout_hybrid_composition',
    'test_driver/android_view_scroll_perf.dart',
    'platform_views_scroll_perf_hybrid_composition',
    testDriver: 'test_driver/scroll_perf_test.dart',
    enableMergedPlatformThread: true,
  ).run;
}

TaskFunction createHomeScrollPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/integration_tests/flutter_gallery',
    'test_driver/scroll_perf.dart',
    'home_scroll_perf',
  ).run;
}

TaskFunction createCullOpacityPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'cull_opacity_perf',
    testDriver: 'test_driver/cull_opacity_perf_test.dart',
  ).run;
}

TaskFunction createCullOpacityPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/cull_opacity_perf_e2e.dart',
  ).run;
}

TaskFunction createCubicBezierPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'cubic_bezier_perf',
    testDriver: 'test_driver/cubic_bezier_perf_test.dart',
  ).run;
}

TaskFunction createCubicBezierPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/cubic_bezier_perf_e2e.dart',
  ).run;
}

TaskFunction createBackdropFilterPerfTest({bool measureCpuGpu = true, bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'backdrop_filter_perf',
    measureCpuGpu: measureCpuGpu,
    testDriver: 'test_driver/backdrop_filter_perf_test.dart',
    saveTraceFile: true,
    enableImpeller: enableImpeller,
    disablePartialRepaint: true,
  ).run;
}

TaskFunction createAnimationWithMicrotasksPerfTest({bool measureCpuGpu = true}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'animation_with_microtasks_perf',
    measureCpuGpu: measureCpuGpu,
    testDriver: 'test_driver/animation_with_microtasks_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createBackdropFilterPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/backdrop_filter_perf_e2e.dart',
  ).run;
}

TaskFunction createPostBackdropFilterPerfTest({bool measureCpuGpu = true}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'post_backdrop_filter_perf',
    measureCpuGpu: measureCpuGpu,
    testDriver: 'test_driver/post_backdrop_filter_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createSimpleAnimationPerfTest({bool measureCpuGpu = true, bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'simple_animation_perf',
    measureCpuGpu: measureCpuGpu,
    testDriver: 'test_driver/simple_animation_perf_test.dart',
    saveTraceFile: true,
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createAnimatedPlaceholderPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/animated_placeholder_perf_e2e.dart',
  ).run;
}

TaskFunction createPictureCachePerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'picture_cache_perf',
    testDriver: 'test_driver/picture_cache_perf_test.dart',
  ).run;
}

TaskFunction createPictureCachePerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/picture_cache_perf_e2e.dart',
  ).run;
}

TaskFunction createPictureCacheComplexityScoringPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'picture_cache_complexity_scoring_perf',
    testDriver: 'test_driver/picture_cache_complexity_scoring_perf_test.dart',
  ).run;
}

TaskFunction createOpenPayScrollPerfTest({bool measureCpuGpu = true}) {
  return PerfTest(
    openpayDirectory.path,
    'test_driver/scroll_perf.dart',
    'openpay_scroll_perf',
    measureCpuGpu: measureCpuGpu,
    testDriver: 'test_driver/scroll_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createFlutterGalleryStartupTest({
  String target = 'lib/main.dart',
  Map<String, String>? runEnvironment,
  bool enableLazyShaderMode = false,
  bool enableHCPP = false,
}) {
  return StartupTest(
    '${flutterDirectory.path}/dev/integration_tests/flutter_gallery',
    target: target,
    runEnvironment: runEnvironment,
    enableLazyShaderMode: enableLazyShaderMode,
    enableHCPP: enableHCPP,
  ).run;
}

TaskFunction createComplexLayoutStartupTest() {
  return StartupTest('${flutterDirectory.path}/dev/benchmarks/complex_layout').run;
}

TaskFunction createFlutterGalleryCompileTest() {
  return CompileTest('${flutterDirectory.path}/dev/integration_tests/flutter_gallery').run;
}

TaskFunction createHelloWorldCompileTest() {
  return CompileTest(
    '${flutterDirectory.path}/examples/hello_world',
    reportPackageContentSizes: true,
  ).run;
}

TaskFunction createImitationGameSwiftUITest() {
  return CompileTest(
    '${flutterDirectory.path}/dev/benchmarks/imitation_game_swiftui',
    reportPackageContentSizes: true,
  ).runSwiftUIApp;
}

TaskFunction createImitationGameFlutterTest() {
  flutter(
    'create',
    options: <String>[
      '--platforms=ios',
      '${flutterDirectory.path}/dev/benchmarks/imitation_game_flutter',
      '--no-overwrite',
    ],
  );
  return CompileTest(
    '${flutterDirectory.path}/dev/benchmarks/imitation_game_flutter',
    reportPackageContentSizes: true,
  ).run;
}

TaskFunction createWebCompileTest() {
  return const WebCompileTest().run;
}

TaskFunction createFlutterViewStartupTest() {
  return StartupTest('${flutterDirectory.path}/examples/flutter_view', reportMetrics: false).run;
}

TaskFunction createPlatformViewStartupTest() {
  return StartupTest('${flutterDirectory.path}/examples/platform_view', reportMetrics: false).run;
}

TaskFunction createBasicMaterialCompileTest() {
  return () async {
    const sampleAppName = 'sample_flutter_app';
    final Directory sampleDir = dir('${Directory.systemTemp.path}/$sampleAppName');

    rmTree(sampleDir);

    await inDirectory<void>(Directory.systemTemp, () async {
      await flutter('create', options: <String>['--template=app', sampleAppName]);
    });

    if (!sampleDir.existsSync()) {
      throw 'Failed to create default Flutter app in ${sampleDir.path}';
    }

    return CompileTest(sampleDir.path).run();
  };
}

TaskFunction createTextfieldPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'textfield_perf',
    testDriver: 'test_driver/textfield_perf_test.dart',
  ).run;
}

TaskFunction createTextfieldPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/textfield_perf_e2e.dart',
  ).run;
}

TaskFunction createVeryLongPictureScrollingPerfE2ETest({required bool enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/very_long_picture_scrolling_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createSlidersPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'sliders_perf',
    testDriver: 'test_driver/sliders_perf_test.dart',
  ).run;
}

TaskFunction createFullscreenTextfieldPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'fullscreen_textfield_perf',
    testDriver: 'test_driver/fullscreen_textfield_perf_test.dart',
  ).run;
}

TaskFunction createFullscreenTextfieldPerfE2ETest({bool? enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/fullscreen_textfield_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createClipperCachePerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/clipper_cache_perf_e2e.dart',
  ).run;
}

TaskFunction createColorFilterAndFadePerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'color_filter_and_fade_perf',
    testDriver: 'test_driver/color_filter_and_fade_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createColorFilterAndFadePerfE2ETest({bool? enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/color_filter_and_fade_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createColorFilterCachePerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/color_filter_cache_perf_e2e.dart',
  ).run;
}

TaskFunction createColorFilterWithUnstableChildPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/color_filter_with_unstable_child_perf_e2e.dart',
  ).run;
}

TaskFunction createShaderMaskCachePerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/shader_mask_cache_perf_e2e.dart',
  ).run;
}

TaskFunction createFadingChildAnimationPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'fading_child_animation_perf',
    testDriver: 'test_driver/fading_child_animation_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createImageFilteredTransformAnimationPerfTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'imagefiltered_transform_animation_perf',
    testDriver: 'test_driver/imagefiltered_transform_animation_perf_test.dart',
    saveTraceFile: true,
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createsMultiWidgetConstructPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/multi_widget_construction_perf_e2e.dart',
  ).run;
}

TaskFunction createListTextLayoutPerfE2ETest({bool? enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/list_text_layout_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createsScrollSmoothnessPerfTest() {
  final testDirectory = '${flutterDirectory.path}/dev/benchmarks/complex_layout';
  const testTarget = 'test/measure_scroll_smoothness.dart';
  return () {
    return inDirectory<TaskResult>(testDirectory, () async {
      final Device device = await devices.workingDevice;
      await device.unlock();
      final String deviceId = device.deviceId;
      await flutter('packages', options: <String>['get']);

      await flutter(
        'drive',
        options: <String>[
          '--no-android-gradle-daemon',
          '-v',
          '--verbose-system-logs',
          '--profile',
          '-t',
          testTarget,
          '-d',
          deviceId,
        ],
      );
      final data =
          json.decode(
                file(
                  '${testOutputDirectory(testDirectory)}/scroll_smoothness_test.json',
                ).readAsStringSync(),
              )
              as Map<String, dynamic>;

      final result = <String, dynamic>{};
      void addResult(dynamic data, String suffix) {
        assert(data is Map<String, dynamic>);
        if (data is Map<String, dynamic>) {
          const metricKeys = <String>['janky_count', 'average_abs_jerk', 'dropped_frame_count'];
          for (final key in metricKeys) {
            result[key + suffix] = data[key];
          }
        }
      }

      addResult(data['resample on with 90Hz input'], '_with_resampler_90Hz');
      addResult(data['resample on with 59Hz input'], '_with_resampler_59Hz');
      addResult(data['resample off with 90Hz input'], '_without_resampler_90Hz');
      addResult(data['resample off with 59Hz input'], '_without_resampler_59Hz');

      return TaskResult.success(result, benchmarkScoreKeys: result.keys.toList());
    });
  };
}

TaskFunction createOpacityPeepholeOneRectPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_one_rect_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeColOfRowsPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_col_of_rows_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeOpacityOfGridPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_opacity_of_grid_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeGridOfOpacityPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_grid_of_opacity_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeFadeTransitionTextPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_fade_transition_text_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeGridOfAlphaSaveLayersPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_grid_of_alpha_savelayers_perf_e2e.dart',
  ).run;
}

TaskFunction createOpacityPeepholeColOfAlphaSaveLayerRowsPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/opacity_peephole_col_of_alpha_savelayer_rows_perf_e2e.dart',
  ).run;
}

TaskFunction createGradientDynamicPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/gradient_dynamic_perf_e2e.dart',
  ).run;
}

TaskFunction createGradientConsistentPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/gradient_consistent_perf_e2e.dart',
  ).run;
}

TaskFunction createGradientStaticPerfE2ETest() {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/gradient_static_perf_e2e.dart',
  ).run;
}

TaskFunction createAnimatedAdvancedBlendPerfTest({bool? enableImpeller, bool? forceOpenGLES}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'animated_advanced_blend_perf',
    enableImpeller: enableImpeller,
    forceOpenGLES: forceOpenGLES,
    testDriver: 'test_driver/animated_advanced_blend_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createRRectBlurPerfTest({bool? enableImpeller, bool? forceOpenGLES}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'rrect_blur_perf',
    enableImpeller: enableImpeller,
    forceOpenGLES: forceOpenGLES,
    testDriver: 'test_driver/rrect_blur_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createAnimatedBlurBackropFilterPerfTest({bool? enableImpeller, bool? forceOpenGLES}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'animated_blur_backdrop_filter_perf',
    enableImpeller: enableImpeller,
    forceOpenGLES: forceOpenGLES,
    testDriver: 'test_driver/animated_blur_backdrop_filter_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createDrawPointsPerfTest({bool? enableImpeller}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'draw_points_perf',
    enableImpeller: enableImpeller,
    testDriver: 'test_driver/draw_points_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createDrawAtlasPerfTest({bool? forceOpenGLES}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'draw_atlas_perf',
    enableImpeller: true,
    testDriver: 'test_driver/draw_atlas_perf_test.dart',
    saveTraceFile: true,
    forceOpenGLES: forceOpenGLES,
  ).run;
}

TaskFunction createDrawVerticesPerfTest({bool? forceOpenGLES}) {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'draw_vertices_perf',
    enableImpeller: true,
    testDriver: 'test_driver/draw_vertices_perf_test.dart',
    saveTraceFile: true,
    forceOpenGLES: forceOpenGLES,
  ).run;
}

TaskFunction createPathTessellationStaticPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'tessellation_perf_static',
    enableImpeller: true,
    testDriver: 'test_driver/path_tessellation_static_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createPathTessellationDynamicPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'tessellation_perf_dynamic',
    enableImpeller: true,
    testDriver: 'test_driver/path_tessellation_dynamic_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createPathStrokeTessellationStaticPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'stroke_tessellation_perf_static',
    enableImpeller: true,
    testDriver: 'test_driver/path_stroke_tessellation_static_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createPathStrokeTessellationDynamicPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'stroke_tessellation_perf_dynamic',
    enableImpeller: true,
    testDriver: 'test_driver/path_stroke_tessellation_dynamic_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createAnimatedComplexOpacityPerfE2ETest({bool? enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/animated_complex_opacity_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createAnimatedComplexImageFilteredPerfE2ETest({bool? enableImpeller}) {
  return PerfTest.e2e(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test/animated_complex_image_filtered_perf_e2e.dart',
    enableImpeller: enableImpeller,
  ).run;
}

TaskFunction createDrawArcsAllFillStylesPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'draw_arcs_all_fill_styles_perf',
    enableImpeller: true,
    testDriver: 'test_driver/draw_arcs_all_fill_styles_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

TaskFunction createDrawArcsAllStrokeStylesPerfTest() {
  return PerfTest(
    '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks',
    'test_driver/run_app.dart',
    'draw_arcs_all_stroke_styles_perf',
    enableImpeller: true,
    testDriver: 'test_driver/draw_arcs_all_stroke_styles_perf_test.dart',
    saveTraceFile: true,
  ).run;
}

Map<String, dynamic> _average(List<Map<String, dynamic>> results, int iterations) {
  final tally = <String, dynamic>{};
  for (final item in results) {
    item.forEach((String key, dynamic value) {
      if (tally.containsKey(key)) {
        tally[key] = (tally[key] as int) + (value as int);
      } else {
        tally[key] = value;
      }
    });
  }
  tally.forEach((String key, dynamic value) {
    tally[key] = (value as int) ~/ iterations;
  });
  return tally;
}

/// Opens the file at testDirectory + 'ios/Runner/Info.plist'
/// and adds additional manifest settings.
void _updateManifestSettings(
  String testDirectory, {
  required bool disablePartialRepaint,
  required bool platformThreadMerged,
}) {
  final String manifestPath = path.join(testDirectory, 'ios', 'Runner', 'Info.plist');
  final file = File(manifestPath);

  if (!file.existsSync()) {
    throw Exception('Info.plist not found at $manifestPath');
  }

  final String xmlStr = file.readAsStringSync();
  final xmlDoc = XmlDocument.parse(xmlStr);
  final keyPairs = <(String, String)>[
    if (disablePartialRepaint) ('FLTDisablePartialRepaint', disablePartialRepaint.toString()),
    if (platformThreadMerged) ('FLTEnableMergedPlatformUIThread', platformThreadMerged.toString()),
  ];

  final XmlElement applicationNode = xmlDoc.findAllElements('dict').first;

  // Check if the meta-data node already exists.
  for (final (String key, String value) in keyPairs) {
    applicationNode.children.add(
      XmlElement(XmlName('key'), <XmlAttribute>[], <XmlNode>[XmlText(key)], false),
    );
    applicationNode.children.add(XmlElement(XmlName(value)));
  }

  file.writeAsStringSync(xmlDoc.toXmlString(pretty: true, indent: '    '));
}

Future<void> _resetPlist(String testDirectory) async {
  final String manifestPath = path.join(testDirectory, 'ios', 'Runner', 'Info.plist');
  final file = File(manifestPath);

  if (!file.existsSync()) {
    throw Exception('Info.plist not found at $manifestPath');
  }

  await exec('git', <String>['checkout', file.path]);
}

void _addMetadataToManifest(String testDirectory, List<(String, String)> keyPairs) {
  final String manifestPath = path.join(
    testDirectory,
    'android',
    'app',
    'src',
    'main',
    'AndroidManifest.xml',
  );
  final file = File(manifestPath);

  if (!file.existsSync()) {
    throw Exception('AndroidManifest.xml not found at $manifestPath');
  }

  final String xmlStr = file.readAsStringSync();
  final xmlDoc = XmlDocument.parse(xmlStr);
  final XmlElement applicationNode = xmlDoc.findAllElements('application').first;

  // Check if the meta-data node already exists.
  for (final (String key, String value) in keyPairs) {
    final Iterable<XmlElement> 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 metaData = XmlElement(XmlName('meta-data'), <XmlAttribute>[
        XmlAttribute(XmlName('android:name'), key),
        XmlAttribute(XmlName('android:value'), value),
      ]);
      applicationNode.children.add(metaData);
    }
  }

  file.writeAsStringSync(xmlDoc.toXmlString(pretty: true, indent: '    '));
}

void _addSurfaceControlSupportToManifest(String testDirectory) {
  final keyPairs = <(String, String)>[
    ('io.flutter.embedding.android.EnableSurfaceControl', 'true'),
  ];
  _addMetadataToManifest(testDirectory, keyPairs);
}

void _addMergedPlatformThreadSupportToManifest(String testDirectory) {
  final keyPairs = <(String, String)>[
    ('io.flutter.embedding.android.EnableMergedPlatformUIThread', 'true'),
  ];
  _addMetadataToManifest(testDirectory, keyPairs);
}

/// Opens the file at testDirectory + 'android/app/src/main/AndroidManifest.xml'
/// <meta-data
///   android:name="io.flutter.embedding.android.EnableVulkanGPUTracing"
///   android:value="true" />
void _addVulkanGPUTracingToManifest(String testDirectory) {
  final keyPairs = <(String, String)>[
    ('io.flutter.embedding.android.EnableVulkanGPUTracing', 'true'),
  ];
  _addMetadataToManifest(testDirectory, keyPairs);
}

/// Opens the file at testDirectory + 'android/app/src/main/AndroidManifest.xml'
/// <meta-data
///   android:name="io.flutter.embedding.android.ImpellerShaderMode"
///   android:value="lazy" />
void _addLazyShaderMode(String testDirectory) {
  final keyPairs = <(String, String)>[
    ('io.flutter.embedding.android.ImpellerLazyShaderInitialization', 'true'),
  ];
  _addMetadataToManifest(testDirectory, keyPairs);
}

/// Opens the file at testDirectory + 'android/app/src/main/AndroidManifest.xml'
/// and adds the following entry to the application.
/// <meta-data
///   android:name="io.flutter.embedding.android.ImpellerBackend"
///   android:value="opengles" />
/// <meta-data
///   android:name="io.flutter.embedding.android.EnableOpenGLGPUTracing"
///   android:value="true" />
void _addOpenGLESToManifest(String testDirectory) {
  final keyPairs = <(String, String)>[
    ('io.flutter.embedding.android.ImpellerBackend', 'opengles'),
    ('io.flutter.embedding.android.EnableOpenGLGPUTracing', 'true'),
  ];
  _addMetadataToManifest(testDirectory, keyPairs);
}

Future<void> _resetManifest(String testDirectory) async {
  final String manifestPath = path.join(
    testDirectory,
    'android',
    'app',
    'src',
    'main',
    'AndroidManifest.xml',
  );
  final file = File(manifestPath);

  if (!file.existsSync()) {
    throw Exception('AndroidManifest.xml not found at $manifestPath');
  }

  await exec('git', <String>['checkout', file.path]);
}

/// Measure application startup performance.
class StartupTest {
  const StartupTest(
    this.testDirectory, {
    this.reportMetrics = true,
    this.target = 'lib/main.dart',
    this.runEnvironment,
    this.enableLazyShaderMode = false,
    this.enableHCPP = false,
  });

  final String testDirectory;
  final bool reportMetrics;
  final bool enableLazyShaderMode;
  final bool enableHCPP;
  final String target;
  final Map<String, String>? runEnvironment;

  Future<TaskResult> run() async {
    return inDirectory<TaskResult>(testDirectory, () async {
      final Device device = await devices.workingDevice;
      await device.unlock();
      const iterations = 5;
      final results = <Map<String, dynamic>>[];

      if (enableLazyShaderMode) {
        _addLazyShaderMode(testDirectory);
      }
      if (enableHCPP) {
        _addSurfaceControlSupportToManifest(testDirectory);
      }

      try {
        section('Building application');
        String? applicationBinaryPath;
        switch (deviceOperatingSystem) {
          case DeviceOperatingSystem.android:
            await flutter(
              'build',
              options: <String>[
                'apk',
                '-v',
                '--profile',
                '--target-platform=android-arm,android-arm64',
                '--target=$target',
              ],
            );
            applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
          case DeviceOperatingSystem.androidArm:
            await flutter(
              'build',
              options: <String>[
                'apk',
                '-v',
                '--profile',
                '--target-platform=android-arm',
                '--target=$target',
              ],
            );
            applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
          case DeviceOperatingSystem.androidArm64:
            await flutter(
              'build',
              options: <String>[
                'apk',
                '-v',
                '--profile',
                '--target-platform=android-arm64',
                '--target=$target',
              ],
            );
            applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
          case DeviceOperatingSystem.fake:
          case DeviceOperatingSystem.fuchsia:
          case DeviceOperatingSystem.linux:
            break;
          case DeviceOperatingSystem.ios:
          case DeviceOperatingSystem.macos:
            await flutter(
              'build',
              options: <String>[
                if (deviceOperatingSystem == DeviceOperatingSystem.ios) 'ios' else 'macos',
                '-v',
                '--profile',
                '--target=$target',
                if (deviceOperatingSystem == DeviceOperatingSystem.ios) '--no-publish-port',
              ],
            );
            final String buildRoot = path.join(testDirectory, 'build');
            applicationBinaryPath = _findDarwinAppInBuildDirectory(buildRoot);
          case DeviceOperatingSystem.webServer:
            break;
          case DeviceOperatingSystem.windows:
            await flutter(
              'build',
              options: <String>['windows', '-v', '--profile', '--target=$target'],
            );
            final String basename = path.basename(testDirectory);
            final arch = Abi.current() == Abi.windowsX64 ? 'x64' : 'arm64';
            applicationBinaryPath = path.join(
              testDirectory,
              'build',
              'windows',
              arch,
              'runner',
              'Profile',
              '$basename.exe',
            );
        }

        const maxFailures = 3;
        var currentFailures = 0;
        for (var i = 0; i < iterations; i += 1) {
          // Startup should not take more than a few minutes. After 10 minutes,
          // take a screenshot to help debug.
          final timer = Timer(const Duration(minutes: 10), () async {
            print('Startup not completed within 10 minutes. Taking a screenshot...');
            await _flutterScreenshot(
              device.deviceId,
              'screenshot_startup_${DateTime.now().toLocal().toIso8601String()}.png',
            );
          });
          final int result = await flutter(
            'run',
            options: <String>[
              '--no-android-gradle-daemon',
              '--no-publish-port',
              '--verbose',
              '--profile',
              '--trace-startup',
              '--target=$target',
              '-d',
              device.deviceId,
              if (applicationBinaryPath != null) '--use-application-binary=$applicationBinaryPath',
            ],
            environment: runEnvironment,
            canFail: true,
          );
          timer.cancel();
          if (result == 0) {
            final data =
                json.decode(
                      file(
                        '${testOutputDirectory(testDirectory)}/start_up_info.json',
                      ).readAsStringSync(),
                    )
                    as Map<String, dynamic>;
            results.add(data);
          } else {
            currentFailures += 1;
            await _flutterScreenshot(
              device.deviceId,
              'screenshot_startup_failure_$currentFailures.png',
            );
            i -= 1;
            if (currentFailures == maxFailures) {
              return TaskResult.failure('Application failed to start $maxFailures times');
            }
          }

          await device.uninstallApp();
        }

        final Map<String, dynamic> averageResults = _average(results, iterations);

        if (!reportMetrics) {
          return TaskResult.success(averageResults);
        }

        return TaskResult.success(
          averageResults,
          benchmarkScoreKeys: <String>[
            'timeToFirstFrameMicros',
            'timeToFirstFrameRasterizedMicros',
          ],
        );
      } finally {
        await _resetManifest(testDirectory);
      }
    });
  }

  Future<void> _flutterScreenshot(String deviceId, String screenshotName) async {
    if (hostAgent.dumpDirectory != null) {
      await flutter(
        'screenshot',
        options: <String>[
          '-d',
          deviceId,
          '--out',
          hostAgent.dumpDirectory!.childFile(screenshotName).path,
        ],
        canFail: true,
      );
    }
  }
}

/// A one-off test to verify that devtools starts in profile mode.
class DevtoolsStartupTest {
  const DevtoolsStartupTest(this.testDirectory);

  final String testDirectory;

  Future<TaskResult> run() async {
    return inDirectory<TaskResult>(testDirectory, () async {
      final Device device = await devices.workingDevice;

      section('Building application');
      String? applicationBinaryPath;
      switch (deviceOperatingSystem) {
        case DeviceOperatingSystem.android:
          await flutter(
            'build',
            options: <String>[
              'apk',
              '-v',
              '--profile',
              '--target-platform=android-arm,android-arm64',
            ],
          );
          applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
        case DeviceOperatingSystem.androidArm:
          await flutter(
            'build',
            options: <String>['apk', '-v', '--profile', '--target-platform=android-arm'],
          );
          applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
        case DeviceOperatingSystem.androidArm64:
          await flutter(
            'build',
            options: <String>['apk', '-v', '--profile', '--target-platform=android-arm64'],
          );
          applicationBinaryPath = '$testDirectory/build/app/outputs/flutter-apk/app-profile.apk';
        case DeviceOperatingSystem.ios:
          await flutter('build', options: <String>['ios', '-v', '--profile']);
          applicationBinaryPath = _findDarwinAppInBuildDirectory(
            '$testDirectory/build/ios/iphoneos',
          );
        case DeviceOperatingSystem.fake:
        case DeviceOperatingSystem.fuchsia:
        case DeviceOperatingSystem.linux:
        case DeviceOperatingSystem.macos:
        case DeviceOperatingSystem.webServer:
        case DeviceOperatingSystem.windows:
          break;
      }

      final Process process = await startFlutter(
        'run',
        options: <String>[
          '--no-android-gradle-daemon',
          '--no-publish-port',
          '--verbose',
          '--profile',
          '-d',
          device.deviceId,
          if (applicationBinaryPath != null) '--use-application-binary=$applicationBinaryPath',
        ],
      );
      final completer = Completer<void>();
      var sawLine = false;
      process.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen((String line) {
        print('[STDOUT]: $line');
        // Wait for devtools output.
        if (line.contains('The Flutter DevTools debugger and profiler')) {
          sawLine = true;
          completer.complete();
        }
      });
      var didExit = false;
      unawaited(
        process.exitCode.whenComplete(() {
          didExit = true;
        }),
      );
      await Future.any(<Future<void>>[
        completer.future,
        Future<void>.delayed(const Duration(minutes: 5)),
        process.exitCode,
      ]);
      if (!didExit) {
        process.stdin.writeln('q');
        await process.exitCode;
      }

      await device.uninstallApp();

      if (sawLine) {
        return TaskResult.success(null, benchmarkScoreKeys: <String>[]);
      }
      return TaskResult.failure(
        'Did not see line "The Flutter DevTools debugger and profiler" in output',
      );
    });
  }
}

/// A callback function to be used to mock the flutter drive command in PerfTests.
///
/// The `options` contains all the arguments in the `flutter drive` command in PerfTests.
typedef FlutterDriveCallback = void Function(List<String> options);

/// Measures application runtime performance, specifically per-frame
/// performance.
class PerfTest {
  const PerfTest(
    this.testDirectory,
    this.testTarget,
    this.timelineFileName, {
    this.measureCpuGpu = true,
    this.measureMemory = true,
    this.measureTotalGCTime = true,
    this.saveTraceFile = false,
    this.testDriver,
    this.needsFullTimeline = true,
    this.benchmarkScoreKeys,
    this.dartDefine = '',
    String? resultFilename,
    this.device,
    this.flutterDriveCallback,
    this.timeoutSeconds,
    this.enableImpeller,
    this.forceOpenGLES,
    this.disablePartialRepaint = false,
    this.enableMergedPlatformThread = false,
    this.enableSurfaceControl = false,
    this.enableLazyShaderMode = false,
    this.createPlatforms = const <String>[],
  }) : _resultFilename = resultFilename;

  const PerfTest.e2e(
    this.testDirectory,
    this.testTarget, {
    this.measureCpuGpu = false,
    this.measureMemory = false,
    this.measureTotalGCTime = false,
    this.testDriver = 'test_driver/e2e_test.dart',
    this.needsFullTimeline = false,
    this.benchmarkScoreKeys = _kCommonScoreKeys,
    this.dartDefine = '',
    String resultFilename = 'e2e_perf_summary',
    this.device,
    this.flutterDriveCallback,
    this.timeoutSeconds,
    this.enableImpeller,
    this.forceOpenGLES,
    this.disablePartialRepaint = false,
    this.enableMergedPlatformThread = false,
    this.enableSurfaceControl = false,
    this.enableLazyShaderMode = false,
    this.createPlatforms = const <String>[],
  }) : saveTraceFile = false,
       timelineFileName = null,
       _resultFilename = resultFilename;

  /// The directory where the app under test is defined.
  final String testDirectory;

  /// The main entry-point file of the application, as run on the device.
  final String testTarget;
  // The prefix name of the filename such as `<timelineFileName>.timeline_summary.json`.
  final String? timelineFileName;
  String get traceFilename => '$timelineFileName.timeline';
  String get resultFilename => _resultFilename ?? '$timelineFileName.timeline_summary';
  final String? _resultFilename;

  /// The test file to run on the host.
  final String? testDriver;

  /// Whether to collect CPU and GPU metrics.
  final bool measureCpuGpu;

  /// Whether to collect memory metrics.
  final bool measureMemory;

  /// Whether to summarize total GC time on the UI thread from the timeline.
  final bool measureTotalGCTime;

  /// Whether to collect full timeline, meaning if `--trace-startup` flag is needed.
  final bool needsFullTimeline;

  /// Whether to save the trace timeline file `*.timeline.json`.
  final bool saveTraceFile;

  /// The device to test on.
  ///
  /// If null, the device is selected depending on the current environment.
  final Device? device;

  /// The function called instead of the actually `flutter drive`.
  ///
  /// If it is not `null`, `flutter drive` will not happen in the PerfTests.
  final FlutterDriveCallback? flutterDriveCallback;

  /// Whether the perf test should enable Impeller.
  final bool? enableImpeller;

  /// Whether the perf test force Impeller's OpenGLES backend.
  final bool? forceOpenGLES;

  /// Whether partial repaint functionality should be disabled (iOS only).
  final bool disablePartialRepaint;

  /// Whether the UI thread should be the platform thread.
  final bool enableMergedPlatformThread;

  /// Whether to enable SurfaceControl swapchain.
  final bool enableSurfaceControl;

  /// Whether to defer construction of all PSO objects in the Impeller backend.
  final bool enableLazyShaderMode;

  /// Number of seconds to time out the test after, allowing debug callbacks to run.
  final int? timeoutSeconds;

  /// The keys of the values that need to be reported.
  ///
  /// If it's `null`, then report:
  /// ```Dart
  /// <String>[
  ///   'average_frame_build_time_millis',
  ///   'worst_frame_build_time_millis',
  ///   '90th_percentile_frame_build_time_millis',
  ///   '99th_percentile_frame_build_time_millis',
  ///   'average_frame_rasterizer_time_millis',
  ///   'worst_frame_rasterizer_time_millis',
  ///   '90th_percentile_frame_rasterizer_time_millis',
  ///   '99th_percentile_frame_rasterizer_time_millis',
  ///   'average_vsync_transitions_missed',
  ///   '90th_percentile_vsync_transitions_missed',
  ///   '99th_percentile_vsync_transitions_missed',
  ///   if (measureCpuGpu) 'average_cpu_usage',
  ///   if (measureCpuGpu) 'average_gpu_usage',
  /// ]
  /// ```
  final List<String>? benchmarkScoreKeys;

  /// Additional flags for `--dart-define` to control the test
  final String dartDefine;

  /// Additional platforms to create with `flutter create` before running
  /// the test.
  final List<String> createPlatforms;

  Future<TaskResult> run() {
    return internalRun();
  }

  @protected
  Future<TaskResult> internalRun({String? existingApp}) {
    return inDirectory<TaskResult>(testDirectory, () async {
      late Device selectedDevice;
      selectedDevice = device ?? await devices.workingDevice;
      await selectedDevice.unlock();
      await selectedDevice.toggleFixedPerformanceMode(true);

      final String deviceId = selectedDevice.deviceId;
      final String? localEngine = localEngineFromEnv;
      final String? localEngineHost = localEngineHostFromEnv;
      final String? localEngineSrcPath = localEngineSrcPathFromEnv;

      if (createPlatforms.isNotEmpty) {
        // Ensure that the platform-specific manifests are freshly created and
        // do not contain any settings from previous runs.
        await exec('git', <String>['clean', '-f', testDirectory]);

        await flutter(
          'create',
          options: <String>['--platforms', createPlatforms.join(','), '--no-overwrite', '.'],
        );
      }

      var changedPlist = false;
      var changedManifest = false;

      Future<void> resetManifest() async {
        if (!changedManifest) {
          return;
        }
        try {
          await _resetManifest(testDirectory);
        } catch (err) {
          print('Caught exception while trying to reset AndroidManifest: $err');
        }
      }

      Future<void> resetPlist() async {
        if (!changedPlist) {
          return;
        }
        try {
          await _resetPlist(testDirectory);
        } catch (err) {
          print('Caught exception while trying to reset Info.plist: $err');
        }
      }

      try {
        if (enableImpeller ?? false) {
          changedManifest = true;
          _addVulkanGPUTracingToManifest(testDirectory);
          if (forceOpenGLES ?? false) {
            _addOpenGLESToManifest(testDirectory);
          }
          if (enableMergedPlatformThread) {
            _addMergedPlatformThreadSupportToManifest(testDirectory);
          }
          if (enableSurfaceControl) {
            _addSurfaceControlSupportToManifest(testDirectory);
          }
          if (enableLazyShaderMode) {
            _addLazyShaderMode(testDirectory);
          }
        }
        if (disablePartialRepaint || enableMergedPlatformThread) {
          changedPlist = true;
          _updateManifestSettings(
            testDirectory,
            disablePartialRepaint: disablePartialRepaint,
            platformThreadMerged: enableMergedPlatformThread,
          );
        }

        final options = <String>[
          if (localEngine != null) ...<String>['--local-engine', localEngine],
          if (localEngineHost != null) ...<String>['--local-engine-host', localEngineHost],
          if (localEngineSrcPath != null) ...<String>[
            '--local-engine-src-path',
            localEngineSrcPath,
          ],
          '--no-android-gradle-daemon',
          '-v',
          '--verbose-system-logs',
          '--profile',
          if (timeoutSeconds != null) ...<String>['--timeout', timeoutSeconds.toString()],
          if (needsFullTimeline) '--trace-startup', // Enables "endless" timeline event buffering.
          '-t', testTarget,
          if (testDriver != null) ...<String>['--driver', testDriver!],
          if (existingApp != null) ...<String>['--use-existing-app', existingApp],
          if (dartDefine.isNotEmpty) ...<String>['--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 {
        await resetManifest();
        await resetPlist();
        await selectedDevice.toggleFixedPerformanceMode(false);
      }

      final data =
          json.decode(
                file(
                  '${testOutputDirectory(testDirectory)}/$resultFilename.json',
                ).readAsStringSync(),
              )
              as Map<String, dynamic>;

      if (data['frame_count'] as int < 5) {
        return TaskResult.failure(
          'Timeline contains too few frames: ${data['frame_count']}. Possibly '
          'trace events are not being captured.',
        );
      }

      final bool recordGPU;
      switch (deviceOperatingSystem) {
        case DeviceOperatingSystem.ios:
          recordGPU = true;
        case DeviceOperatingSystem.android:
        case DeviceOperatingSystem.androidArm:
        case DeviceOperatingSystem.androidArm64:
          recordGPU = true;
        case DeviceOperatingSystem.fake:
        case DeviceOperatingSystem.fuchsia:
        case DeviceOperatingSystem.linux:
        case DeviceOperatingSystem.macos:
        case DeviceOperatingSystem.webServer:
        case DeviceOperatingSystem.windows:
          recordGPU = false;
      }

      final isAndroid = deviceOperatingSystem == DeviceOperatingSystem.android;
      return TaskResult.success(
        data,
        detailFiles: <String>[
          if (saveTraceFile) '${testOutputDirectory(testDirectory)}/$traceFilename.json',
        ],
        benchmarkScoreKeys:
            benchmarkScoreKeys ??
            <String>[
              ..._kCommonScoreKeys,
              'average_vsync_transitions_missed',
              '90th_percentile_vsync_transitions_missed',
              '99th_percentile_vsync_transitions_missed',
              if (measureCpuGpu && !isAndroid) ...<String>[
                // See https://github.com/flutter/flutter/issues/68888
                if (data['average_cpu_usage'] != null) 'average_cpu_usage',
                if (data['average_gpu_usage'] != null) 'average_gpu_usage',
              ],
              if (measureMemory && !isAndroid) ...<String>[
                // See https://github.com/flutter/flutter/issues/68888
                if (data['average_memory_usage'] != null) 'average_memory_usage',
                if (data['90th_percentile_memory_usage'] != null) '90th_percentile_memory_usage',
                if (data['99th_percentile_memory_usage'] != null) '99th_percentile_memory_usage',
              ],
              if (measureTotalGCTime) 'total_ui_gc_time',
              if (data['30hz_frame_percentage'] != null) '30hz_frame_percentage',
              if (data['60hz_frame_percentage'] != null) '60hz_frame_percentage',
              if (data['80hz_frame_percentage'] != null) '80hz_frame_percentage',
              if (data['90hz_frame_percentage'] != null) '90hz_frame_percentage',
              if (data['120hz_frame_percentage'] != null) '120hz_frame_percentage',
              if (data['illegal_refresh_rate_frame_count'] != null)
                'illegal_refresh_rate_frame_count',
              if (recordGPU) ...<String>[
                // GPU Frame Time.
                if (data['average_gpu_frame_time'] != null) 'average_gpu_frame_time',
                if (data['90th_percentile_gpu_frame_time'] != null)
                  '90th_percentile_gpu_frame_time',
                if (data['99th_percentile_gpu_frame_time'] != null)
                  '99th_percentile_gpu_frame_time',
                if (data['worst_gpu_frame_time'] != null) 'worst_gpu_frame_time',
                // GPU Memory.
                if (data['average_gpu_memory_mb'] != null) 'average_gpu_memory_mb',
                if (data['90th_percentile_gpu_memory_mb'] != null) '90th_percentile_gpu_memory_mb',
                if (data['99th_percentile_gpu_memory_mb'] != null) '99th_percentile_gpu_memory_mb',
                if (data['worst_gpu_memory_mb'] != null) 'worst_gpu_memory_mb',
              ],
            ],
      );
    });
  }
}

const List<String> _kCommonScoreKeys = <String>[
  'average_frame_build_time_millis',
  'worst_frame_build_time_millis',
  '90th_percentile_frame_build_time_millis',
  '99th_percentile_frame_build_time_millis',
  'average_frame_rasterizer_time_millis',
  'worst_frame_rasterizer_time_millis',
  '90th_percentile_frame_rasterizer_time_millis',
  '99th_percentile_frame_rasterizer_time_millis',
  'old_gen_gc_count',
];

/// Measures how long it takes to compile a Flutter app to JavaScript and how
/// big the compiled code is.
class WebCompileTest {
  const WebCompileTest();

  Future<TaskResult> run() async {
    final metrics = <String, Object>{};

    metrics.addAll(
      await runSingleBuildTest(
        directory: '${flutterDirectory.path}/examples/hello_world',
        metric: 'hello_world',
      ),
    );

    metrics.addAll(
      await runSingleBuildTest(
        directory: '${flutterDirectory.path}/dev/integration_tests/flutter_gallery',
        metric: 'flutter_gallery',
      ),
    );

    const sampleAppName = 'sample_flutter_app';
    final Directory sampleDir = dir('${Directory.systemTemp.path}/$sampleAppName');

    rmTree(sampleDir);

    await inDirectory<void>(Directory.systemTemp, () async {
      await flutter('create', options: <String>['--template=app', sampleAppName]);
    });

    metrics.addAll(
      await runSingleBuildTest(directory: sampleDir.path, metric: 'basic_material_app'),
    );

    return TaskResult.success(metrics, benchmarkScoreKeys: metrics.keys.toList());
  }

  /// Run a single web compile test and return its metrics.
  ///
  /// Run a single web compile test for the app under [directory], and store
  /// its metrics with prefix [metric].
  static Future<Map<String, int>> runSingleBuildTest({
    required String directory,
    required String metric,
    bool measureBuildTime = false,
  }) {
    return inDirectory<Map<String, int>>(directory, () async {
      final metrics = <String, int>{};

      await flutter('clean');
      await flutter('packages', options: <String>['get']);
      final Stopwatch? watch = measureBuildTime ? Stopwatch() : null;
      watch?.start();
      await evalFlutter(
        'build',
        options: <String>['web', '-v', '--release', '--no-pub', '--no-web-resources-cdn'],
      );
      watch?.stop();
      final String buildDir = path.join(directory, 'build', 'web');
      metrics.addAll(
        await getSize(
          directories: <String, String>{'web_build_dir': buildDir},
          files: <String, String>{
            'dart2js': path.join(buildDir, 'main.dart.js'),
            'canvaskit_wasm': path.join(buildDir, 'canvaskit', 'canvaskit.wasm'),
            'canvaskit_js': path.join(buildDir, 'canvaskit', 'canvaskit.js'),
            'flutter_js': path.join(buildDir, 'flutter.js'),
          },
          metric: metric,
        ),
      );

      if (measureBuildTime) {
        metrics['${metric}_dart2js_millis'] = watch!.elapsedMilliseconds;
      }

      return metrics;
    });
  }

  /// Obtains the size and gzipped size of both [dartBundleFile] and [buildDir].
  static Future<Map<String, int>> getSize({
    /// Mapping of metric key name to file system path for directories to measure
    Map<String, String> directories = const <String, String>{},

    /// Mapping of metric key name to file system path for files to measure
    Map<String, String> files = const <String, String>{},
    required String metric,
  }) async {
    const kGzipCompressionLevel = '-9';
    final sizeMetrics = <String, int>{};

    final Directory tempDir = Directory.systemTemp.createTempSync('perf_tests_gzips');
    try {
      for (final MapEntry<String, String> entry in files.entries) {
        final String key = entry.key;
        final String filePath = entry.value;
        sizeMetrics['${metric}_${key}_uncompressed_bytes'] = File(filePath).lengthSync();

        await Process.run('gzip', <String>['--keep', kGzipCompressionLevel, filePath]);
        // gzip does not provide a CLI option to specify an output file, so
        // instead just move the output file to the temp dir
        final File compressedFile = File(
          '$filePath.gz',
        ).renameSync(path.join(tempDir.absolute.path, '$key.gz'));
        sizeMetrics['${metric}_${key}_compressed_bytes'] = compressedFile.lengthSync();
      }

      for (final MapEntry<String, String> entry in directories.entries) {
        final String key = entry.key;
        final String dirPath = entry.value;

        final String tarball = path.join(tempDir.absolute.path, '$key.tar');
        await Process.run('tar', <String>['--create', '--verbose', '--file=$tarball', dirPath]);
        sizeMetrics['${metric}_${key}_uncompressed_bytes'] = File(tarball).lengthSync();

        // get size of compressed build directory
        await Process.run('gzip', <String>['--keep', kGzipCompressionLevel, tarball]);
        sizeMetrics['${metric}_${key}_compressed_bytes'] = File('$tarball.gz').lengthSync();
      }
    } finally {
      try {
        tempDir.deleteSync(recursive: true);
      } on FileSystemException {
        print('Failed to delete ${tempDir.path}.');
      }
    }
    return sizeMetrics;
  }
}

/// Measures how long it takes to compile a Flutter app and how big the compiled
/// code is.
class CompileTest {
  const CompileTest(this.testDirectory, {this.reportPackageContentSizes = false});

  final String testDirectory;
  final bool reportPackageContentSizes;

  Future<TaskResult> run() async {
    return inDirectory<TaskResult>(testDirectory, () async {
      await flutter('packages', options: <String>['get']);

      // "initial" compile required downloading and creating the `android/.gradle` directory while "full"
      // compiles only run `flutter clean` between runs.
      final Map<String, dynamic> compileInitialRelease = await _compileApp(deleteGradleCache: true);
      final Map<String, dynamic> compileFullRelease = await _compileApp(deleteGradleCache: false);
      final Map<String, dynamic> compileInitialDebug = await _compileDebug(
        clean: true,
        deleteGradleCache: true,
        metricKey: 'debug_initial_compile_millis',
      );
      final Map<String, dynamic> compileFullDebug = await _compileDebug(
        clean: true,
        deleteGradleCache: false,
        metricKey: 'debug_full_compile_millis',
      );
      // Build again without cleaning, should be faster.
      final Map<String, dynamic> compileSecondDebug = await _compileDebug(
        clean: false,
        deleteGradleCache: false,
        metricKey: 'debug_second_compile_millis',
      );

      final metrics = <String, dynamic>{
        ...compileInitialRelease,
        ...compileFullRelease,
        ...compileInitialDebug,
        ...compileFullDebug,
        ...compileSecondDebug,
      };

      final mainDart = File('$testDirectory/lib/main.dart');
      if (mainDart.existsSync()) {
        final List<int> bytes = mainDart.readAsBytesSync();
        // "Touch" the file
        mainDart.writeAsStringSync(' ', mode: FileMode.append, flush: true);
        // Build after "edit" without clean should be faster than first build
        final Map<String, dynamic> compileAfterEditDebug = await _compileDebug(
          clean: false,
          deleteGradleCache: false,
          metricKey: 'debug_compile_after_edit_millis',
        );
        metrics.addAll(compileAfterEditDebug);
        // Revert the changes
        mainDart.writeAsBytesSync(bytes, flush: true);
      }

      return TaskResult.success(metrics, benchmarkScoreKeys: metrics.keys.toList());
    });
  }

  Future<List<double>> getMetricsFromXCResults(String xcResultsBundleName) async {
    return inDirectory<List<double>>(testDirectory, () async {
      var resultsJson = <dynamic>[];

      // First, grab the id from the info.plist.
      final ProcessResult plistIDResult = await Process.run(
        workingDirectory: testDirectory,
        'plutil',
        <String>['-extract', 'rootId.hash', 'raw', '-o', '-', '$xcResultsBundleName/Info.plist'],
      );

      final String plistID = plistIDResult.stdout.toString().trim();

      // Next, get the ActionsInvocationRecord and Extract the testsRef ID
      var testRefID = '';
      await Process.run(workingDirectory: testDirectory, 'xcrun', <String>[
        'xcresulttool',
        'get',
        '--path',
        xcResultsBundleName,
        '--id',
        plistID,
        '--format',
        'json',
        '--legacy',
      ]).then((ProcessResult result) {
        final dynamic actionsInvocationRecordJSON = json.decode(result.stdout.toString());
        print(result.stdout);

        testRefID =
            // ignore: avoid_dynamic_calls
            actionsInvocationRecordJSON['actions']['_values'][0]['actionResult']['testsRef']['id']['_value']
                .toString();
      });

      // Next, grab the ActionTestSummary using our testRefID.
      var actionTestSummaryID = '';
      await Process.run(workingDirectory: testDirectory, 'xcrun', <String>[
        'xcresulttool',
        'get',
        '--path',
        xcResultsBundleName,
        '--id',
        testRefID,
        '--format',
        'json',
        '--legacy',
      ]).then((ProcessResult result) {
        final dynamic actionTestSummaryJSON = json.decode(result.stdout.toString());

        actionTestSummaryID =
            // ignore: avoid_dynamic_calls
            actionTestSummaryJSON['summaries']['_values'][0]['testableSummaries']['_values'][0]['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'][0]['summaryRef']['id']['_value']
                .toString();
      });

      dynamic resultMetricsJSON = '';

      // Finally, grab the metrics.
      await Process.run(workingDirectory: testDirectory, 'xcrun', <String>[
        'xcresulttool',
        'get',
        '--path',
        xcResultsBundleName,
        '--id',
        actionTestSummaryID,
        '--format',
        'json',
        '--legacy',
      ]).then((ProcessResult result) {
        resultMetricsJSON = json.decode(result.stdout.toString());

        resultsJson =
            // ignore: avoid_dynamic_calls
            resultMetricsJSON['performanceMetrics']['_values'][0]['measurements']['_values']
                as List<dynamic>;
      });
      final extractedLaunchTimes = <double>[];
      resultsJson
          .map(
            (dynamic item) => extractedLaunchTimes.add(
              double.parse((item as Map<String, dynamic>)['_value'] as String),
            ),
          )
          .toList();

      return extractedLaunchTimes;
    });
  }

  Future<TaskResult> runSwiftUIApp() async {
    return inDirectory<TaskResult>(testDirectory, () async {
      final Map<String, String> environment = Platform.environment;
      final String developmentTeam = environment['FLUTTER_XCODE_DEVELOPMENT_TEAM'] ?? 'S8QB4VV633';
      final String? codeSignStyle = environment['FLUTTER_XCODE_CODE_SIGN_STYLE'];
      final String? provisioningProfile =
          environment['FLUTTER_XCODE_PROVISIONING_PROFILE_SPECIFIER'];

      await Process.run('xcodebuild', <String>['clean', '-allTargets']);

      /* Compile Time */
      var releaseSizeInBytes = 0;
      final watch = Stopwatch();

      watch.start();
      await Process.run(workingDirectory: testDirectory, 'xcodebuild', <String>[
        '-allowProvisioningUpdates',
        '-scheme',
        'hello_world_swiftui',
        '-target',
        'hello_world_swiftui',
        '-sdk',
        'iphoneos',
        '-configuration',
        'Release',
        '-archivePath',
        '$testDirectory/hello_world_swiftui',
        'archive',
        'DEVELOPMENT_TEAM=$developmentTeam',
        'CODE_SIGN_STYLE=$codeSignStyle',
        'PROVISIONING_PROFILE_SPECIFIER=$provisioningProfile',
      ]).then((ProcessResult results) {
        watch.stop();
        print(results.stdout);
        if (results.exitCode != 0) {
          print(results.stderr);
        }
      });

      /* App Size */
      final appPath =
          '$testDirectory/hello_world_swiftui.xcarchive/Products/Applications/hello_world_swiftui.app';

      // Zip up the .app file to get an approximation of the .ipa size.
      await exec('tar', <String>['-zcf', 'app.tar.gz', appPath]);
      releaseSizeInBytes = await file('$testDirectory/app.tar.gz').length();

      /* Time to First Frame */
      const resultBundleName = 'benchmarkResults.xcresult';
      await Process.run(workingDirectory: testDirectory, 'rm', <String>[
        '-rf',
        '$testDirectory/$resultBundleName',
      ]).then((ProcessResult results) {
        print(results.stdout);
      });

      // Run the benchmarking tests, and create the xcResults file.
      await Process.run(workingDirectory: testDirectory, 'xcodebuild', <String>[
        'test',
        '-project',
        'hello_world_swiftui.xcodeproj',
        '-scheme',
        'hello_world_swiftui',
        '-destination',
        'platform=iOS',
        '-only-testing:BenchmarkTests/BenchmarkTests/testTimeToFirstFrame',
        '-resultBundlePath',
        '$testDirectory/$resultBundleName',
        '-verbose',
        'DEVELOPMENT_TEAM=$developmentTeam',
        'CODE_SIGN_STYLE=$codeSignStyle',
        'PROVISIONING_PROFILE_SPECIFIER=$provisioningProfile',
      ]);

      final List<double> extractedLaunchTimes = await getMetricsFromXCResults(resultBundleName);

      final metrics = <String, dynamic>{};
      metrics.addAll(<String, dynamic>{
        'release_swiftui_compile_millis': watch.elapsedMilliseconds,
        'release_swiftui_size_bytes': releaseSizeInBytes,
        'time_to_first_frame': extractedLaunchTimes.average,
      });
      return TaskResult.success(metrics);
    });
  }

  Future<Map<String, dynamic>> _compileApp({required bool deleteGradleCache}) async {
    await flutter('clean');
    if (deleteGradleCache) {
      final gradleCacheDir = Directory('$testDirectory/android/.gradle');
      rmTree(gradleCacheDir);
    }
    final watch = Stopwatch();
    int releaseSizeInBytes;
    final options = <String>['--release'];
    final metrics = <String, dynamic>{};

    switch (deviceOperatingSystem) {
      case DeviceOperatingSystem.ios:
      case DeviceOperatingSystem.macos:
        unawaited(stderr.flush());
        late final String deviceId;
        if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
          deviceId = 'ios';
        } else if (deviceOperatingSystem == DeviceOperatingSystem.macos) {
          deviceId = 'macos';
        } else {
          throw Exception('Attempted to run darwin compile workflow with $deviceOperatingSystem');
        }

        options.insert(0, deviceId);
        options.add('--tree-shake-icons');
        options.add('--split-debug-info=infos/');
        watch.start();
        await flutter('build', options: options);
        watch.stop();
        final Directory buildDirectory = dir(path.join(cwd, 'build'));
        final String? appPath = _findDarwinAppInBuildDirectory(buildDirectory.path);
        if (appPath == null) {
          throw 'Failed to find app bundle in ${buildDirectory.path}';
        }
        // Validate changes in Dart snapshot format and data layout do not
        // change compression size. This also simulates the size of an IPA on iOS.
        await exec('tar', <String>['-zcf', 'build/app.tar.gz', appPath]);
        releaseSizeInBytes = await file('$cwd/build/app.tar.gz').length();
        if (reportPackageContentSizes) {
          final Map<String, Object> sizeMetrics = await getSizesFromDarwinApp(
            appPath: appPath,
            operatingSystem: deviceOperatingSystem,
          );
          metrics.addAll(sizeMetrics);
        }
      case DeviceOperatingSystem.android:
      case DeviceOperatingSystem.androidArm:
        options.insert(0, 'apk');
        options.add('--target-platform=android-arm');
        options.add('--tree-shake-icons');
        options.add('--split-debug-info=infos/');
        watch.start();
        await flutter('build', options: options);
        watch.stop();
        final apkPath = '$cwd/build/app/outputs/flutter-apk/app-release.apk';
        final File apk = file(apkPath);
        releaseSizeInBytes = apk.lengthSync();
        if (reportPackageContentSizes) {
          metrics.addAll(await getSizesFromApk(apkPath));
        }
      case DeviceOperatingSystem.androidArm64:
        options.insert(0, 'apk');
        options.add('--target-platform=android-arm64');
        options.add('--tree-shake-icons');
        options.add('--split-debug-info=infos/');
        watch.start();
        await flutter('build', options: options);
        watch.stop();
        final apkPath = '$cwd/build/app/outputs/flutter-apk/app-release.apk';
        final File apk = file(apkPath);
        releaseSizeInBytes = apk.lengthSync();
        if (reportPackageContentSizes) {
          metrics.addAll(await getSizesFromApk(apkPath));
        }
      case DeviceOperatingSystem.fake:
        throw Exception('Unsupported option for fake devices');
      case DeviceOperatingSystem.fuchsia:
        throw Exception('Unsupported option for Fuchsia devices');
      case DeviceOperatingSystem.linux:
        throw Exception('Unsupported option for Linux devices');
      case DeviceOperatingSystem.webServer:
        throw Exception('Unsupported option for Web Server devices');
      case DeviceOperatingSystem.windows:
        unawaited(stderr.flush());
        options.insert(0, 'windows');
        options.add('--tree-shake-icons');
        options.add('--split-debug-info=infos/');
        watch.start();
        await flutter('build', options: options);
        watch.stop();
        final String basename = path.basename(cwd);
        final arch = Abi.current() == Abi.windowsX64 ? 'x64' : 'arm64';
        final String exePath = path.join(
          cwd,
          'build',
          'windows',
          arch,
          'runner',
          'release',
          '$basename.exe',
        );
        final File exe = file(exePath);
        // On Windows, we do not produce a single installation package file,
        // rather a directory containing an .exe and .dll files.
        // The release size is set to the size of the produced .exe file
        releaseSizeInBytes = exe.lengthSync();
    }

    metrics.addAll(<String, dynamic>{
      'release_${deleteGradleCache ? 'initial' : 'full'}_compile_millis': watch.elapsedMilliseconds,
      'release_size_bytes': releaseSizeInBytes,
    });

    return metrics;
  }

  Future<Map<String, dynamic>> _compileDebug({
    required bool deleteGradleCache,
    required bool clean,
    required String metricKey,
  }) async {
    if (clean) {
      await flutter('clean');
    }
    if (deleteGradleCache) {
      final gradleCacheDir = Directory('$testDirectory/android/.gradle');
      rmTree(gradleCacheDir);
    }
    final watch = Stopwatch();
    final options = <String>['--debug'];
    switch (deviceOperatingSystem) {
      case DeviceOperatingSystem.ios:
        options.insert(0, 'ios');
      case DeviceOperatingSystem.android:
      case DeviceOperatingSystem.androidArm:
        options.insert(0, 'apk');
        options.add('--target-platform=android-arm');
      case DeviceOperatingSystem.androidArm64:
        options.insert(0, 'apk');
        options.add('--target-platform=android-arm64');
      case DeviceOperatingSystem.fake:
        throw Exception('Unsupported option for fake devices');
      case DeviceOperatingSystem.fuchsia:
        throw Exception('Unsupported option for Fuchsia devices');
      case DeviceOperatingSystem.linux:
        throw Exception('Unsupported option for Linux devices');
      case DeviceOperatingSystem.macos:
        unawaited(stderr.flush());
        options.insert(0, 'macos');
      case DeviceOperatingSystem.webServer:
        throw Exception('Unsupported option for Web Server devices');
      case DeviceOperatingSystem.windows:
        unawaited(stderr.flush());
        options.insert(0, 'windows');
    }
    watch.start();
    await flutter('build', options: options);
    watch.stop();

    return <String, dynamic>{metricKey: watch.elapsedMilliseconds};
  }

  static Future<Map<String, Object>> getSizesFromDarwinApp({
    required String appPath,
    required DeviceOperatingSystem operatingSystem,
  }) async {
    late final File flutterFramework;
    late final String frameworkDirectory;
    switch (deviceOperatingSystem) {
      case DeviceOperatingSystem.ios:
        frameworkDirectory = path.join(appPath, 'Frameworks');
        flutterFramework = File(path.join(frameworkDirectory, 'Flutter.framework', 'Flutter'));
      case DeviceOperatingSystem.macos:
        frameworkDirectory = path.join(appPath, 'Contents', 'Frameworks');
        flutterFramework = File(
          path.join(frameworkDirectory, 'FlutterMacOS.framework', 'FlutterMacOS'),
        ); // https://github.com/flutter/flutter/issues/70413
      case DeviceOperatingSystem.android:
      case DeviceOperatingSystem.androidArm:
      case DeviceOperatingSystem.androidArm64:
      case DeviceOperatingSystem.fake:
      case DeviceOperatingSystem.fuchsia:
      case DeviceOperatingSystem.linux:
      case DeviceOperatingSystem.webServer:
      case DeviceOperatingSystem.windows:
        throw Exception('Called ${CompileTest.getSizesFromDarwinApp} with $operatingSystem.');
    }

    final appFramework = File(path.join(frameworkDirectory, 'App.framework', 'App'));

    return <String, Object>{
      'app_framework_uncompressed_bytes': await appFramework.length(),
      'flutter_framework_uncompressed_bytes': await flutterFramework.length(),
    };
  }

  static Future<Map<String, dynamic>> getSizesFromApk(String apkPath) async {
    final String output = await eval('unzip', <String>['-v', apkPath]);
    final List<String> lines = output.split('\n');
    final fileToMetadata = <String, _UnzipListEntry>{};

    // First three lines are header, last two lines are footer.
    for (var i = 3; i < lines.length - 2; i++) {
      final entry = _UnzipListEntry.fromLine(lines[i]);
      fileToMetadata[entry.path] = entry;
    }

    final _UnzipListEntry libflutter = fileToMetadata['lib/armeabi-v7a/libflutter.so']!;
    final _UnzipListEntry libapp = fileToMetadata['lib/armeabi-v7a/libapp.so']!;
    final _UnzipListEntry license = fileToMetadata['assets/flutter_assets/NOTICES.Z']!;

    return <String, dynamic>{
      'libflutter_uncompressed_bytes': libflutter.uncompressedSize,
      'libflutter_compressed_bytes': libflutter.compressedSize,
      'libapp_uncompressed_bytes': libapp.uncompressedSize,
      'libapp_compressed_bytes': libapp.compressedSize,
      'license_uncompressed_bytes': license.uncompressedSize,
      'license_compressed_bytes': license.compressedSize,
    };
  }
}

/// Measure application memory usage.
class MemoryTest {
  MemoryTest(this.project, this.test, this.package, {this.requiresTapToStart = false});

  final String project;
  final String test;
  final String package;
  final bool requiresTapToStart;

  /// Completes when the log line specified in the last call to
  /// [prepareForNextMessage] is seen by `adb logcat`.
  Future<void>? get receivedNextMessage => _receivedNextMessage?.future;
  Completer<void>? _receivedNextMessage;
  String? _nextMessage;

  /// Prepares the [receivedNextMessage] future such that it will complete
  /// when `adb logcat` sees a log line with the given `message`.
  void prepareForNextMessage(String message) {
    _nextMessage = message;
    _receivedNextMessage = Completer<void>();
  }

  int get iterationCount => 10;

  Device? get device => _device;
  Device? _device;

  Future<TaskResult> run() {
    return inDirectory<TaskResult>(project, () async {
      // This test currently only works on Android, because device.logcat,
      // device.getMemoryStats, etc, aren't implemented for iOS.

      _device = await devices.workingDevice;
      await device!.unlock();
      await flutter('packages', options: <String>['get']);

      final StreamSubscription<String> adb = device!.logcat.listen((String data) {
        if (data.contains('==== MEMORY BENCHMARK ==== $_nextMessage ====')) {
          _receivedNextMessage?.complete();
        }
      });

      for (var iteration = 0; iteration < iterationCount; iteration += 1) {
        print('running memory test iteration $iteration...');
        _startMemoryUsage = null;
        await useMemory();
        assert(_startMemoryUsage != null);
        assert(_startMemory.length == iteration + 1);
        assert(_endMemory.length == iteration + 1);
        assert(_diffMemory.length == iteration + 1);
        print('terminating...');
        await device!.stop(package);
        await Future<void>.delayed(const Duration(milliseconds: 10));
      }

      await adb.cancel();
      await device!.uninstallApp();

      final startMemoryStatistics = ListStatistics(_startMemory);
      final endMemoryStatistics = ListStatistics(_endMemory);
      final diffMemoryStatistics = ListStatistics(_diffMemory);

      final memoryUsage = <String, dynamic>{
        ...startMemoryStatistics.asMap('start'),
        ...endMemoryStatistics.asMap('end'),
        ...diffMemoryStatistics.asMap('diff'),
      };

      _device = null;
      _startMemory.clear();
      _endMemory.clear();
      _diffMemory.clear();

      return TaskResult.success(memoryUsage, benchmarkScoreKeys: memoryUsage.keys.toList());
    });
  }

  /// Starts the app specified by [test] on the [device].
  ///
  /// The [run] method will terminate it by its package name ([package]).
  Future<void> launchApp() async {
    prepareForNextMessage('READY');
    print('launching $project$test on device...');
    await flutter(
      'run',
      options: <String>['--verbose', '--release', '--no-resident', '-d', device!.deviceId, test],
    );
    print('awaiting "ready" message...');
    await receivedNextMessage;
  }

  /// Taps the application and looks for acknowledgement.
  ///
  /// This is used by several tests to ensure scrolling gestures are installed.
  Future<void> tapNotification() async {
    // Keep "tapping" the device till it responds with the string we expect,
    // or throw an error instead of tying up the infrastructure for 30 minutes.
    prepareForNextMessage('TAPPED');
    var tapped = false;
    var tapCount = 0;
    await Future.any(<Future<void>>[
      () async {
        while (true) {
          if (tapped) {
            break;
          }
          tapCount += 1;
          print('tapping device... [$tapCount]');
          await device!.tap(100, 100);
          await Future<void>.delayed(const Duration(milliseconds: 100));
        }
      }(),
      () async {
        print('awaiting "tapped" message... (timeout: 10 seconds)');
        try {
          await receivedNextMessage?.timeout(const Duration(seconds: 10));
        } finally {
          tapped = true;
        }
      }(),
    ]);
  }

  /// To change the behavior of the test, override this.
  ///
  /// Make sure to call recordStart() and recordEnd() once each in that order.
  ///
  /// By default it just launches the app, records memory usage, taps the device,
  /// awaits a DONE notification, and records memory usage again.
  Future<void> useMemory() async {
    await launchApp();
    await recordStart();
    if (requiresTapToStart) {
      await tapNotification();
    }

    prepareForNextMessage('DONE');
    print('awaiting "done" message...');
    await receivedNextMessage;

    await recordEnd();
  }

  final List<int> _startMemory = <int>[];
  final List<int> _endMemory = <int>[];
  final List<int> _diffMemory = <int>[];

  Map<String, dynamic>? _startMemoryUsage;

  @protected
  Future<void> recordStart() async {
    assert(_startMemoryUsage == null);
    print('snapshotting memory usage...');
    _startMemoryUsage = await device!.getMemoryStats(package);
  }

  @protected
  Future<void> recordEnd() async {
    assert(_startMemoryUsage != null);
    print('snapshotting memory usage...');
    final Map<String, dynamic> endMemoryUsage = await device!.getMemoryStats(package);
    _startMemory.add(_startMemoryUsage!['total_kb'] as int);
    _endMemory.add(endMemoryUsage['total_kb'] as int);
    _diffMemory.add((endMemoryUsage['total_kb'] as int) - (_startMemoryUsage!['total_kb'] as int));
  }
}

class DevToolsMemoryTest {
  DevToolsMemoryTest(this.project, this.driverTest);

  final String project;
  final String driverTest;

  Future<TaskResult> run() {
    return inDirectory<TaskResult>(project, () async {
      _device = await devices.workingDevice;
      await _device.unlock();

      await flutter(
        'drive',
        driveWithDds: true,
        options: <String>[
          '-d',
          _device.deviceId,
          '--profile',
          '--profile-memory',
          _kJsonFileName,
          '--no-publish-port',
          '-v',
          driverTest,
        ],
      );

      final data =
          json.decode(file('$project/$_kJsonFileName').readAsStringSync()) as Map<String, dynamic>;
      final samples = (data['samples'] as Map<String, dynamic>)['data'] as List<dynamic>;
      var maxRss = 0;
      var maxAdbTotal = 0;
      for (final Map<String, dynamic> sample in samples.cast<Map<String, dynamic>>()) {
        if (sample['rss'] != null) {
          maxRss = math.max(maxRss, sample['rss'] as int);
        }
        if (sample['adb_memoryInfo'] != null) {
          maxAdbTotal = math.max(
            maxAdbTotal,
            (sample['adb_memoryInfo'] as Map<String, dynamic>)['Total'] as int,
          );
        }
      }

      return TaskResult.success(
        <String, dynamic>{'maxRss': maxRss, 'maxAdbTotal': maxAdbTotal},
        benchmarkScoreKeys: <String>['maxRss', 'maxAdbTotal'],
      );
    });
  }

  late Device _device;

  static const String _kJsonFileName = 'devtools_memory.json';
}

enum ReportedDurationTestFlavor { debug, profile, release }

String _reportedDurationTestToString(ReportedDurationTestFlavor flavor) {
  return switch (flavor) {
    ReportedDurationTestFlavor.debug => 'debug',
    ReportedDurationTestFlavor.profile => 'profile',
    ReportedDurationTestFlavor.release => 'release',
  };
}

class ReportedDurationTest {
  ReportedDurationTest(this.flavor, this.project, this.test, this.package, this.durationPattern);

  final ReportedDurationTestFlavor flavor;
  final String project;
  final String test;
  final String package;
  final RegExp durationPattern;

  final Completer<int> durationCompleter = Completer<int>();

  int get iterationCount => 10;

  Device? get device => _device;
  Device? _device;

  Future<TaskResult> run() {
    return inDirectory<TaskResult>(project, () async {
      // This test currently only works on Android, because device.logcat,
      // device.getMemoryStats, etc, aren't implemented for iOS.

      _device = await devices.workingDevice;
      await device!.unlock();
      await flutter('packages', options: <String>['get']);

      final StreamSubscription<String> adb = device!.logcat.listen((String data) {
        if (durationPattern.hasMatch(data)) {
          durationCompleter.complete(int.parse(durationPattern.firstMatch(data)!.group(1)!));
        }
      });
      print('launching $project$test on device...');
      await flutter(
        'run',
        options: <String>[
          '--verbose',
          '--no-publish-port',
          '--${_reportedDurationTestToString(flavor)}',
          '--no-resident',
          '-d',
          device!.deviceId,
          test,
        ],
      );

      final int duration = await durationCompleter.future;
      print('terminating...');
      await device!.stop(package);
      await adb.cancel();

      _device = null;

      final reportedDuration = <String, dynamic>{'duration': duration};
      _device = null;

      return TaskResult.success(
        reportedDuration,
        benchmarkScoreKeys: reportedDuration.keys.toList(),
      );
    });
  }
}

/// Holds simple statistics of an odd-lengthed list of integers.
class ListStatistics {
  factory ListStatistics(Iterable<int> data) {
    assert(data.isNotEmpty);
    assert(data.length.isOdd);
    final List<int> sortedData = data.toList()..sort();
    return ListStatistics._(
      sortedData.first,
      sortedData.last,
      sortedData[(sortedData.length - 1) ~/ 2],
    );
  }

  const ListStatistics._(this.min, this.max, this.median);

  final int min;
  final int max;
  final int median;

  Map<String, int> asMap(String prefix) {
    return <String, int>{'$prefix-min': min, '$prefix-max': max, '$prefix-median': median};
  }
}

class _UnzipListEntry {
  factory _UnzipListEntry.fromLine(String line) {
    final List<String> data = line.trim().split(RegExp(r'\s+'));
    assert(data.length == 8);
    return _UnzipListEntry._(
      uncompressedSize: int.parse(data[0]),
      compressedSize: int.parse(data[2]),
      path: data[7],
    );
  }

  _UnzipListEntry._({
    required this.uncompressedSize,
    required this.compressedSize,
    required this.path,
  }) : assert(compressedSize <= uncompressedSize);

  final int uncompressedSize;
  final int compressedSize;
  final String path;
}

/// Wait for up to 1 hour for the file to appear.
Future<File> waitForFile(String path) async {
  for (var i = 0; i < 180; i += 1) {
    final file = File(path);
    print('looking for ${file.path}');
    if (file.existsSync()) {
      return file;
    }
    await Future<void>.delayed(const Duration(seconds: 20));
  }
  throw StateError('Did not find vmservice out file after 1 hour');
}

String? _findDarwinAppInBuildDirectory(String searchDirectory) {
  for (final FileSystemEntity entity in Directory(searchDirectory).listSync(recursive: true)) {
    if (entity.path.endsWith('.app')) {
      return entity.path;
    }
  }
  return null;
}
