[flutter_tools] Fix slow ios_device_start_prebuilt_test (#59026)

diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index c7ccb55..674a6fc 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -6,8 +6,8 @@
 import 'dart:math' as math;
 
 import 'package:meta/meta.dart';
-import 'package:vm_service/vm_service.dart' as vm_service;
 import 'package:process/process.dart';
+import 'package:vm_service/vm_service.dart' as vm_service;
 
 import '../application_package.dart';
 import '../artifacts.dart';
@@ -154,6 +154,7 @@
     @required IOSDeploy iosDeploy,
     @required IMobileDevice iMobileDevice,
     @required Logger logger,
+    @required VmServiceConnector vmServiceConnectUri,
   })
     : _sdkVersion = sdkVersion,
       _iosDeploy = iosDeploy,
@@ -161,6 +162,7 @@
       _fileSystem = fileSystem,
       _logger = logger,
       _platform = platform,
+      _vmServiceConnectUri = vmServiceConnectUri,
         super(
           id,
           category: Category.mobile,
@@ -185,6 +187,7 @@
   final Logger _logger;
   final Platform _platform;
   final IMobileDevice _iMobileDevice;
+  final VmServiceConnector _vmServiceConnectUri;
 
   /// May be 0 if version cannot be parsed.
   int get majorSdkVersion {
@@ -431,6 +434,7 @@
         protocolDiscovery: observatoryDiscovery,
         flutterUsage: globals.flutterUsage,
         pollingDelay: fallbackPollingDelay,
+        vmServiceConnectUri: _vmServiceConnectUri,
       );
       final Uri localUri = await fallbackDiscovery.discover(
         assumedDevicePort: assumedObservatoryPort,
diff --git a/packages/flutter_tools/lib/src/ios/fallback_discovery.dart b/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
index f4c4956..32634f5 100644
--- a/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
+++ b/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
@@ -4,7 +4,6 @@
 
 import 'package:meta/meta.dart';
 import 'package:vm_service/vm_service.dart';
-import 'package:vm_service/vm_service_io.dart' as vm_service_io;
 
 import '../base/io.dart';
 import '../base/logger.dart';
@@ -44,8 +43,7 @@
     @required Logger logger,
     @required ProtocolDiscovery protocolDiscovery,
     @required Usage flutterUsage,
-    VmServiceConnector vmServiceConnectUri =
-      vm_service_io.vmServiceConnectUri,
+    @required VmServiceConnector vmServiceConnectUri,
     Duration pollingDelay,
   }) : _logger = logger,
        _mDnsObservatoryDiscovery = mDnsObservatoryDiscovery,
@@ -137,7 +135,7 @@
   // Returns `null` if no connection can be made.
   Future<Uri> _attemptServiceConnection({
     @required int assumedDevicePort,
-    @required int  hostVmservicePort,
+    @required int hostVmservicePort,
     @required String packageName,
   }) async {
     int hostPort;
diff --git a/packages/flutter_tools/lib/src/macos/xcode.dart b/packages/flutter_tools/lib/src/macos/xcode.dart
index 191fff8..81a430c 100644
--- a/packages/flutter_tools/lib/src/macos/xcode.dart
+++ b/packages/flutter_tools/lib/src/macos/xcode.dart
@@ -6,6 +6,7 @@
 
 import 'package:meta/meta.dart';
 import 'package:process/process.dart';
+import 'package:vm_service/vm_service_io.dart' as vm_service_io;
 
 import '../artifacts.dart';
 import '../base/common.dart';
@@ -501,6 +502,7 @@
         iosDeploy: _iosDeploy,
         iMobileDevice: _iMobileDevice,
         platform: globals.platform,
+        vmServiceConnectUri: vm_service_io.vmServiceConnectUri,
       ));
     }
     return devices;
diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
index e5a16bb..522c976 100644
--- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
@@ -21,6 +21,7 @@
 import 'package:flutter_tools/src/ios/mac.dart';
 import 'package:flutter_tools/src/macos/xcode.dart';
 import 'package:mockito/mockito.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -35,6 +36,7 @@
     final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
     Artifacts mockArtifacts;
     MockCache mockCache;
+    MockVmService mockVmService;
     Logger logger;
     IOSDeploy iosDeploy;
     IMobileDevice iMobileDevice;
@@ -43,6 +45,7 @@
     setUp(() {
       mockArtifacts = MockArtifacts();
       mockCache = MockCache();
+      mockVmService = MockVmService();
       const MapEntry<String, String> dyLdLibEntry = MapEntry<String, String>('DYLD_LIBRARY_PATH', '/path/to/libs');
       when(mockCache.dyLdLibEntry).thenReturn(dyLdLibEntry);
       logger = BufferLogger.test();
@@ -74,6 +77,7 @@
         sdkVersion: '13.3',
         cpuArchitecture: DarwinArch.arm64,
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       );
     });
 
@@ -90,6 +94,7 @@
         cpuArchitecture: DarwinArch.arm64,
         sdkVersion: '1.0.0',
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       ).majorSdkVersion, 1);
       expect(IOSDevice(
         'device-123',
@@ -103,6 +108,7 @@
         cpuArchitecture: DarwinArch.arm64,
         sdkVersion: '13.1.1',
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       ).majorSdkVersion, 13);
       expect(IOSDevice(
         'device-123',
@@ -116,6 +122,7 @@
         cpuArchitecture: DarwinArch.arm64,
         sdkVersion: '10',
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       ).majorSdkVersion, 10);
       expect(IOSDevice(
         'device-123',
@@ -129,6 +136,7 @@
         cpuArchitecture: DarwinArch.arm64,
         sdkVersion: '0',
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       ).majorSdkVersion, 0);
       expect(IOSDevice(
         'device-123',
@@ -142,6 +150,7 @@
         cpuArchitecture: DarwinArch.arm64,
         sdkVersion: 'bogus',
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       ).majorSdkVersion, 0);
     });
 
@@ -158,6 +167,7 @@
         sdkVersion: '13.3',
         cpuArchitecture: DarwinArch.arm64,
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
       );
 
       expect(device.supportsRuntimeMode(BuildMode.debug), true);
@@ -182,6 +192,7 @@
               sdkVersion: '13.3',
               cpuArchitecture: DarwinArch.arm64,
               interfaceType: IOSDeviceInterface.usb,
+              vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
             );
           },
           throwsAssertionError,
@@ -266,6 +277,7 @@
           sdkVersion: '13.3',
           cpuArchitecture: DarwinArch.arm64,
           interfaceType: IOSDeviceInterface.usb,
+          vmServiceConnectUri: (String string, {Log log}) async => mockVmService,
         );
         logReader1 = createLogReader(device, appPackage1, mockProcess1);
         logReader2 = createLogReader(device, appPackage2, mockProcess2);
@@ -287,6 +299,8 @@
     MockXcdevice mockXcdevice;
     MockArtifacts mockArtifacts;
     MockCache mockCache;
+    MockVmService mockVmService1;
+    MockVmService mockVmService2;
     FakeProcessManager fakeProcessManager;
     BufferLogger logger;
     IOSDeploy iosDeploy;
@@ -299,6 +313,8 @@
       mockXcdevice = MockXcdevice();
       mockArtifacts = MockArtifacts();
       mockCache = MockCache();
+      mockVmService1 = MockVmService();
+      mockVmService2 = MockVmService();
       logger = BufferLogger.test();
       mockIosWorkflow = MockIOSWorkflow();
       fakeProcessManager = FakeProcessManager.any();
@@ -328,6 +344,7 @@
         platform: macPlatform,
         fileSystem: MemoryFileSystem.test(),
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService1,
       );
 
       device2 = IOSDevice(
@@ -342,6 +359,7 @@
         platform: macPlatform,
         fileSystem: MemoryFileSystem.test(),
         interfaceType: IOSDeviceInterface.usb,
+        vmServiceConnectUri: (String string, {Log log}) async => mockVmService2,
       );
     });
 
@@ -549,3 +567,4 @@
 class MockIOSDeploy extends Mock implements IOSDeploy {}
 class MockIOSWorkflow extends Mock implements IOSWorkflow {}
 class MockXcdevice extends Mock implements XCDevice {}
+class MockVmService extends Mock implements VmService {}
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_install_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_install_test.dart
index d8e9214..a36f5dd 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_install_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_install_test.dart
@@ -16,6 +16,7 @@
 import 'package:flutter_tools/src/ios/mac.dart';
 import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -302,8 +303,10 @@
     ),
     artifacts: artifacts,
     interfaceType: interfaceType,
+    vmServiceConnectUri: (String string, {Log log}) async => MockVmService(),
   );
 }
 
 class MockArtifacts extends Mock implements Artifacts {}
 class MockCache extends Mock implements Cache {}
+class MockVmService extends Mock implements VmService {}
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_project_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_project_test.dart
index d09ead7..6444bd0 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_project_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_project_test.dart
@@ -11,6 +11,7 @@
 import 'package:flutter_tools/src/ios/devices.dart';
 import 'package:flutter_tools/src/project.dart';
 import 'package:mockito/mockito.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -90,7 +91,9 @@
     cpuArchitecture: DarwinArch.arm64,
     artifacts: artifacts,
     interfaceType: IOSDeviceInterface.usb,
+    vmServiceConnectUri: (String string, {Log log}) async => MockVmService(),
   );
 }
 
 class MockArtifacts extends Mock implements Artifacts {}
+class MockVmService extends Mock implements VmService {}
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
index fa95eda..0bae7ec 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
@@ -19,6 +19,7 @@
 import 'package:flutter_tools/src/project.dart';
 import 'package:mockito/mockito.dart';
 import 'package:quiver/testing/async.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -333,6 +334,7 @@
     ),
     cpuArchitecture: DarwinArch.arm64,
     interfaceType: IOSDeviceInterface.usb,
+    vmServiceConnectUri: (String string, {Log log}) async => MockVmService(),
   );
 }
 
@@ -340,3 +342,4 @@
 class MockCache extends Mock implements Cache {}
 class MockXcode extends Mock implements Xcode {}
 class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
+class MockVmService extends Mock implements VmService {}
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart
index 5ab6343..b8feb3d 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_start_prebuilt_test.dart
@@ -8,6 +8,7 @@
 import 'package:flutter_tools/src/application_package.dart';
 import 'package:flutter_tools/src/artifacts.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/io.dart' as io;
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -15,11 +16,13 @@
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:flutter_tools/src/ios/devices.dart';
+import 'package:flutter_tools/src/ios/fallback_discovery.dart';
 import 'package:flutter_tools/src/ios/ios_deploy.dart';
 import 'package:flutter_tools/src/ios/mac.dart';
 import 'package:flutter_tools/src/mdns_discovery.dart';
 import 'package:flutter_tools/src/reporting/reporting.dart';
 import 'package:mockito/mockito.dart';
+import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -106,6 +109,12 @@
     final IOSDevice device = setUpIOSDevice(
       processManager: processManager,
       fileSystem: fileSystem,
+      vmServiceConnector: (String string, {Log log}) async {
+        throw const io.SocketException(
+          'OS Error: Connection refused, errno = 61, address = localhost, port '
+          '= 58943',
+        );
+      },
     );
     final IOSApp iosApp = PrebuiltIOSApp(
       projectBundleId: 'app',
@@ -122,8 +131,11 @@
     device.portForwarder = const NoOpDevicePortForwarder();
     device.setLogReader(iosApp, FakeDeviceLogReader());
 
-    when(MDnsObservatoryDiscovery.instance.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
-      .thenAnswer((Invocation invocation) async => uri);
+    when(MDnsObservatoryDiscovery.instance.getObservatoryUri(
+      any,
+      any,
+      usesIpv6: anyNamed('usesIpv6')
+    )).thenAnswer((Invocation invocation) async => uri);
 
     final LaunchResult launchResult = await device.startApp(iosApp,
       prebuiltApplication: true,
@@ -151,6 +163,12 @@
     final IOSDevice device = setUpIOSDevice(
       processManager: processManager,
       fileSystem: fileSystem,
+      vmServiceConnector: (String string, {Log log}) async {
+        throw const io.SocketException(
+          'OS Error: Connection refused, errno = 61, address = localhost, port '
+          '= 58943',
+        );
+      },
     );
     final IOSApp iosApp = PrebuiltIOSApp(
       projectBundleId: 'app',
@@ -198,6 +216,12 @@
     final IOSDevice device = setUpIOSDevice(
       processManager: processManager,
       fileSystem: fileSystem,
+      vmServiceConnector: (String string, {Log log}) async {
+        throw const io.SocketException(
+          'OS Error: Connection refused, errno = 61, address = localhost, port '
+          '= 58943',
+        );
+      },
     );
     final IOSApp iosApp = PrebuiltIOSApp(
       projectBundleId: 'app',
@@ -315,6 +339,12 @@
       sdkVersion: '13.3',
       processManager: processManager,
       fileSystem: fileSystem,
+      vmServiceConnector: (String string, {Log log}) async {
+        throw const io.SocketException(
+          'OS Error: Connection refused, errno = 61, address = localhost, port '
+          '= 58943',
+        );
+      },
     );
     final IOSApp iosApp = PrebuiltIOSApp(
       projectBundleId: 'app',
@@ -331,8 +361,11 @@
     device.setLogReader(iosApp, FakeDeviceLogReader());
     device.portForwarder = const NoOpDevicePortForwarder();
 
-    when(MDnsObservatoryDiscovery.instance.getObservatoryUri(any, any, usesIpv6: anyNamed('usesIpv6')))
-      .thenAnswer((Invocation invocation) async => uri);
+    when(MDnsObservatoryDiscovery.instance.getObservatoryUri(
+      any,
+      any,
+      usesIpv6: anyNamed('usesIpv6'),
+    )).thenAnswer((Invocation invocation) async => uri);
 
     final LaunchResult launchResult = await device.startApp(iosApp,
       prebuiltApplication: true,
@@ -368,6 +401,7 @@
   FileSystem fileSystem,
   Logger logger,
   ProcessManager processManager,
+  VmServiceConnector vmServiceConnector,
 }) {
   const MapEntry<String, String> dyldLibraryEntry = MapEntry<String, String>(
     'DYLD_LIBRARY_PATH',
@@ -379,6 +413,7 @@
     operatingSystem: 'macos',
     environment: <String, String>{},
   );
+  vmServiceConnector ??= (String uri, {Log log}) async => MockVmService();
   when(cache.dyLdLibEntry).thenReturn(dyldLibraryEntry);
   when(artifacts.getArtifactPath(Artifact.iosDeploy, platform: anyNamed('platform')))
     .thenReturn('ios-deploy');
@@ -404,6 +439,7 @@
     ),
     cpuArchitecture: DarwinArch.arm64,
     interfaceType: IOSDeviceInterface.usb,
+    vmServiceConnectUri: vmServiceConnector,
   );
 }
 
@@ -413,3 +449,4 @@
 class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {}
 class MockArtifacts extends Mock implements Artifacts {}
 class MockCache extends Mock implements Cache {}
+class MockVmService extends Mock implements VmService {}