Inject Usage dependency into FallbackDiscovery and BuildEvent (#53443)

* Usage dependency injection

* Review edits
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index a91159a..73a36dd 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -242,9 +242,9 @@
 
   final bool usesAndroidX = isAppUsingAndroidX(project.android.hostAppGradleRoot);
   if (usesAndroidX) {
-    BuildEvent('app-using-android-x').send();
+    BuildEvent('app-using-android-x', flutterUsage: globals.flutterUsage).send();
   } else if (!usesAndroidX) {
-    BuildEvent('app-not-using-android-x').send();
+    BuildEvent('app-not-using-android-x', flutterUsage: globals.flutterUsage).send();
     globals.printStatus("$warningMark Your app isn't using AndroidX.", emphasis: true);
     globals.printStatus(
       'To avoid potential build failures, you can quickly migrate your app '
@@ -404,7 +404,7 @@
 
   if (exitCode != 0) {
     if (detectedGradleError == null) {
-      BuildEvent('gradle-unkown-failure').send();
+      BuildEvent('gradle-unkown-failure', flutterUsage: globals.flutterUsage).send();
       throwToolExit(
         'Gradle task $assembleTask failed with exit code $exitCode',
         exitCode: exitCode,
@@ -430,7 +430,7 @@
               shouldBuildPluginAsAar: shouldBuildPluginAsAar,
               retries: retries - 1,
             );
-            BuildEvent(successEventLabel).send();
+            BuildEvent(successEventLabel, flutterUsage: globals.flutterUsage).send();
             return;
           case GradleBuildStatus.retryWithAarPlugins:
             await buildGradleApp(
@@ -442,13 +442,13 @@
               shouldBuildPluginAsAar: true,
               retries: retries - 1,
             );
-            BuildEvent(successEventLabel).send();
+            BuildEvent(successEventLabel, flutterUsage: globals.flutterUsage).send();
             return;
           case GradleBuildStatus.exit:
             // noop.
         }
       }
-      BuildEvent('gradle-${detectedGradleError.eventLabel}-failure').send();
+      BuildEvent('gradle-${detectedGradleError.eventLabel}-failure', flutterUsage: globals.flutterUsage).send();
       throwToolExit(
         'Gradle task $assembleTask failed with exit code $exitCode',
         exitCode: exitCode,
@@ -697,7 +697,7 @@
 }
 
 void _exitWithUnsupportedProjectMessage() {
-  BuildEvent('unsupported-project', eventError: 'gradle-plugin').send();
+  BuildEvent('unsupported-project', eventError: 'gradle-plugin', flutterUsage: globals.flutterUsage).send();
   throwToolExit(
     '$warningMark Your app is using an unsupported Gradle project. '
     'To fix this problem, create a new project by running `flutter create -t app <app-directory>` '
@@ -706,7 +706,7 @@
 }
 
 void _exitWithProjectNotUsingGradleMessage() {
-  BuildEvent('unsupported-project', eventError: 'app-not-using-gradle').send();
+  BuildEvent('unsupported-project', eventError: 'app-not-using-gradle', flutterUsage: globals.flutterUsage).send();
   throwToolExit(
     '$warningMark The build process for Android has changed, and the '
     'current project configuration is no longer valid. Please consult\n\n'
@@ -770,7 +770,7 @@
     } on ToolExit {
       // Log the entire plugin entry in `.flutter-plugins` since it
       // includes the plugin name and the version.
-      BuildEvent('gradle-plugin-aar-failure', eventError: plugin).send();
+      BuildEvent('gradle-plugin-aar-failure', eventError: plugin, flutterUsage: globals.flutterUsage).send();
       throwToolExit('The plugin $pluginName could not be built due to the issue above.');
     }
   }
@@ -866,12 +866,13 @@
   assert(fileExtension != null);
 
   final String androidGradlePluginVersion =
-      getGradleVersionForAndroidPlugin(project.android.hostAppGradleRoot);
+  getGradleVersionForAndroidPlugin(project.android.hostAppGradleRoot);
   BuildEvent('gradle-expected-file-not-found',
     settings:
-      'androidGradlePluginVersion: $androidGradlePluginVersion, '
-      'fileExtension: $fileExtension'
-    ).send();
+    'androidGradlePluginVersion: $androidGradlePluginVersion, '
+      'fileExtension: $fileExtension',
+    flutterUsage: globals.flutterUsage,
+  ).send();
   throwToolExit(
     'Gradle build failed to produce an $fileExtension file. '
     "It's likely that this file was generated under ${project.android.buildDirectory.path}, "
diff --git a/packages/flutter_tools/lib/src/android/gradle_errors.dart b/packages/flutter_tools/lib/src/android/gradle_errors.dart
index fddea7c..d505214 100644
--- a/packages/flutter_tools/lib/src/android/gradle_errors.dart
+++ b/packages/flutter_tools/lib/src/android/gradle_errors.dart
@@ -183,6 +183,7 @@
       BuildEvent(
         'gradle-android-x-failure',
         eventError: 'app-not-using-plugins',
+        flutterUsage: globals.flutterUsage,
       ).send();
     }
     if (hasPlugins && !usesAndroidX) {
@@ -195,6 +196,7 @@
       BuildEvent(
         'gradle-android-x-failure',
         eventError: 'app-not-using-androidx',
+        flutterUsage: globals.flutterUsage,
       ).send();
     }
     if (hasPlugins && usesAndroidX && shouldBuildPluginAsAar) {
@@ -204,6 +206,7 @@
       BuildEvent(
         'gradle-android-x-failure',
         eventError: 'using-jetifier',
+        flutterUsage: globals.flutterUsage,
       ).send();
     }
     if (hasPlugins && usesAndroidX && !shouldBuildPluginAsAar) {
@@ -214,6 +217,7 @@
       BuildEvent(
         'gradle-android-x-failure',
         eventError: 'not-using-jetifier',
+        flutterUsage: globals.flutterUsage,
       ).send();
       return GradleBuildStatus.retryWithAarPlugins;
     }
diff --git a/packages/flutter_tools/lib/src/android/gradle_utils.dart b/packages/flutter_tools/lib/src/android/gradle_utils.dart
index 491fd12..0b7b92d 100644
--- a/packages/flutter_tools/lib/src/android/gradle_utils.dart
+++ b/packages/flutter_tools/lib/src/android/gradle_utils.dart
@@ -301,7 +301,7 @@
 }
 
 void exitWithNoSdkMessage() {
-  BuildEvent('unsupported-project', eventError: 'android-sdk-not-found').send();
+  BuildEvent('unsupported-project', eventError: 'android-sdk-not-found', flutterUsage: globals.flutterUsage).send();
   throwToolExit(
     '$warningMark No Android SDK found. '
     'Try setting the ANDROID_HOME environment variable.'
diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart
index a5342ee..ee31990 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios.dart
@@ -89,7 +89,7 @@
     );
 
     if (!result.success) {
-      await diagnoseXcodeBuildFailure(result);
+      await diagnoseXcodeBuildFailure(result, globals.flutterUsage, globals.logger);
       throwToolExit('Encountered error while building for $logTarget.');
     }
 
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 00ab2d5..fe77a53 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -220,6 +220,7 @@
         platform: globals.platform,
         fileSystem: globals.fs,
         terminal: globals.terminal,
+        usage: globals.flutterUsage,
       ),
     },
   );
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index faf1218..f08c66a 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -242,7 +242,7 @@
       );
       if (!buildResult.success) {
         _logger.printError('Could not build the precompiled application for the device.');
-        await diagnoseXcodeBuildFailure(buildResult);
+        await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, _logger);
         _logger.printError('');
         return LaunchResult.failed();
       }
@@ -338,6 +338,7 @@
         mDnsObservatoryDiscovery: MDnsObservatoryDiscovery.instance,
         portForwarder: portForwarder,
         protocolDiscovery: observatoryDiscovery,
+        flutterUsage: globals.flutterUsage,
       );
       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 90a28e3..0d5aa4b 100644
--- a/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
+++ b/packages/flutter_tools/lib/src/ios/fallback_discovery.dart
@@ -9,7 +9,6 @@
 import '../base/io.dart';
 import '../base/logger.dart';
 import '../device.dart';
-import '../globals.dart' as globals;
 import '../mdns_discovery.dart';
 import '../protocol_discovery.dart';
 import '../reporting/reporting.dart';
@@ -42,12 +41,14 @@
     @required MDnsObservatoryDiscovery mDnsObservatoryDiscovery,
     @required Logger logger,
     @required ProtocolDiscovery protocolDiscovery,
+    @required Usage flutterUsage,
     Future<VmService> Function(String wsUri, {Log log}) vmServiceConnectUri =
       vm_service_io.vmServiceConnectUri,
   }) : _logger = logger,
        _mDnsObservatoryDiscovery = mDnsObservatoryDiscovery,
        _portForwarder = portForwarder,
        _protocolDiscovery = protocolDiscovery,
+       _flutterUsage = flutterUsage,
        _vmServiceConnectUri = vmServiceConnectUri;
 
   static const String _kEventName = 'ios-handshake';
@@ -56,6 +57,7 @@
   final MDnsObservatoryDiscovery _mDnsObservatoryDiscovery;
   final Logger _logger;
   final ProtocolDiscovery _protocolDiscovery;
+  final Usage _flutterUsage;
   final Future<VmService> Function(String wsUri, {Log log}) _vmServiceConnectUri;
 
   /// Attempt to discover the observatory port.
@@ -87,7 +89,7 @@
         UsageEvent(
           _kEventName,
           'mdns-success',
-          flutterUsage: globals.flutterUsage,
+          flutterUsage: _flutterUsage,
         ).send();
         return result;
       }
@@ -98,7 +100,7 @@
     UsageEvent(
       _kEventName,
       'mdns-failure',
-      flutterUsage: globals.flutterUsage,
+      flutterUsage: _flutterUsage,
     ).send();
 
     try {
@@ -107,7 +109,7 @@
         UsageEvent(
           _kEventName,
           'fallback-success',
-          flutterUsage: globals.flutterUsage,
+          flutterUsage: _flutterUsage,
         ).send();
         return result;
       }
@@ -121,7 +123,7 @@
     UsageEvent(
       _kEventName,
       'fallback-failure',
-      flutterUsage: globals.flutterUsage,
+      flutterUsage: _flutterUsage,
     ).send();
     return null;
   }
@@ -167,7 +169,7 @@
             UsageEvent(
               _kEventName,
               'success',
-              flutterUsage: globals.flutterUsage,
+              flutterUsage: _flutterUsage,
             ).send();
             return Uri.parse('http://localhost:$hostPort');
           }
@@ -207,7 +209,7 @@
       _kEventName,
       eventAction,
       label: eventLabel,
-      flutterUsage: globals.flutterUsage,
+      flutterUsage: _flutterUsage,
     ).send();
   }
 }
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 3894bdb..e4ded3f 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -342,6 +342,7 @@
     if (e.toString().contains('timed out')) {
       BuildEvent('xcode-show-build-settings-timeout',
         command: showBuildSettingsCommand.join(' '),
+        flutterUsage: globals.flutterUsage,
       ).send();
     }
     rethrow;
@@ -447,13 +448,14 @@
     result.stdout.contains('there are two concurrent builds running');
 }
 
-Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result) async {
+Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsage, Logger logger) async {
   if (result.xcodeBuildExecution != null &&
       result.xcodeBuildExecution.buildForPhysicalDevice &&
       result.stdout?.toUpperCase()?.contains('BITCODE') == true) {
     BuildEvent('xcode-bitcode-failure',
       command: result.xcodeBuildExecution.buildCommands.toString(),
       settings: result.xcodeBuildExecution.buildSettings.toString(),
+      flutterUsage: flutterUsage,
     ).send();
   }
 
@@ -463,11 +465,11 @@
   if (result.stdout?.contains('Building for iOS') == true
       && result.stdout?.contains('but the linked and embedded framework') == true
       && result.stdout?.contains('was built for iOS') == true) {
-    globals.printError('');
-    globals.printError('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
-    globals.printError('');
-    globals.printError('You can temporarily work around this issue by running:');
-    globals.printError('  rm -rf ios/Flutter/App.framework');
+    logger.printError('');
+    logger.printError('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.');
+    logger.printError('');
+    logger.printError('You can temporarily work around this issue by running:');
+    logger.printError('  rm -rf ios/Flutter/App.framework');
     return;
   }
 
@@ -476,7 +478,7 @@
       result.stdout?.contains('BCEROR') == true &&
       // May need updating if Xcode changes its outputs.
       result.stdout?.contains("Xcode couldn't find a provisioning profile matching") == true) {
-    globals.printError(noProvisioningProfileInstruction, emphasis: true);
+    logger.printError(noProvisioningProfileInstruction, emphasis: true);
     return;
   }
   // Make sure the user has specified one of:
@@ -486,26 +488,26 @@
       result.xcodeBuildExecution.buildForPhysicalDevice &&
       !<String>['DEVELOPMENT_TEAM', 'PROVISIONING_PROFILE'].any(
         result.xcodeBuildExecution.buildSettings.containsKey)) {
-    globals.printError(noDevelopmentTeamInstruction, emphasis: true);
+    logger.printError(noDevelopmentTeamInstruction, emphasis: true);
     return;
   }
   if (result.xcodeBuildExecution != null &&
       result.xcodeBuildExecution.buildForPhysicalDevice &&
       result.xcodeBuildExecution.buildSettings['PRODUCT_BUNDLE_IDENTIFIER']?.contains('com.example') == true) {
-    globals.printError('');
-    globals.printError('It appears that your application still contains the default signing identifier.');
-    globals.printError("Try replacing 'com.example' with your signing id in Xcode:");
-    globals.printError('  open ios/Runner.xcworkspace');
+    logger.printError('');
+    logger.printError('It appears that your application still contains the default signing identifier.');
+    logger.printError("Try replacing 'com.example' with your signing id in Xcode:");
+    logger.printError('  open ios/Runner.xcworkspace');
     return;
   }
   if (result.stdout?.contains('Code Sign error') == true) {
-    globals.printError('');
-    globals.printError('It appears that there was a problem signing your application prior to installation on the device.');
-    globals.printError('');
-    globals.printError('Verify that the Bundle Identifier in your project is your signing id in Xcode');
-    globals.printError('  open ios/Runner.xcworkspace');
-    globals.printError('');
-    globals.printError("Also try selecting 'Product > Build' to fix the problem:");
+    logger.printError('');
+    logger.printError('It appears that there was a problem signing your application prior to installation on the device.');
+    logger.printError('');
+    logger.printError('Verify that the Bundle Identifier in your project is your signing id in Xcode');
+    logger.printError('  open ios/Runner.xcworkspace');
+    logger.printError('');
+    logger.printError("Also try selecting 'Product > Build' to fix the problem:");
     return;
   }
 }
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index b8e2432..12709d9 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -254,17 +254,20 @@
     @required Logger logger,
     @required FileSystem fileSystem,
     @required Terminal terminal,
+    @required Usage usage,
   }) : _platform = platform,
-       _fileSystem = fileSystem,
-       _terminal = terminal,
-       _logger = logger,
-       _processUtils = ProcessUtils(logger: logger, processManager: processManager);
+      _fileSystem = fileSystem,
+      _terminal = terminal,
+      _logger = logger,
+      _processUtils = ProcessUtils(logger: logger, processManager: processManager),
+      _usage = usage;
 
   final Platform _platform;
   final FileSystem _fileSystem;
   final ProcessUtils _processUtils;
   final Terminal _terminal;
   final Logger _logger;
+  final Usage _usage;
 
   static const String _executable = '/usr/bin/xcodebuild';
   static final RegExp _versionRegex = RegExp(r'Xcode ([0-9.]+)');
@@ -359,6 +362,7 @@
       if (error is ProcessException && error.toString().contains('timed out')) {
         BuildEvent('xcode-show-build-settings-timeout',
           command: showBuildSettingsCommand.join(' '),
+          flutterUsage: _usage,
         ).send();
       }
       _logger.printTrace('Unexpected failure to get the build settings: $error.');
diff --git a/packages/flutter_tools/lib/src/reporting/events.dart b/packages/flutter_tools/lib/src/reporting/events.dart
index 0053ce6..8b0274b 100644
--- a/packages/flutter_tools/lib/src/reporting/events.dart
+++ b/packages/flutter_tools/lib/src/reporting/events.dart
@@ -135,10 +135,14 @@
 /// An event that reports something about a build.
 class BuildEvent extends UsageEvent {
   BuildEvent(String label, {
-    this.command,
-    this.settings,
-    this.eventError,
-  }) : super(
+    String command,
+    String settings,
+    String eventError,
+    @required Usage flutterUsage,
+  }) : _command = command,
+  _settings = settings,
+  _eventError = eventError,
+      super(
     // category
     'build',
     // parameter
@@ -146,22 +150,22 @@
       ? 'unspecified'
       : FlutterCommand.current.name,
     label: label,
-    flutterUsage: globals.flutterUsage,
+    flutterUsage: flutterUsage,
   );
 
-  final String command;
-  final String settings;
-  final String eventError;
+  final String _command;
+  final String _settings;
+  final String _eventError;
 
   @override
   void send() {
     final Map<String, String> parameters = _useCdKeys(<CustomDimensions, String>{
-      if (command != null)
-        CustomDimensions.buildEventCommand: command,
-      if (settings != null)
-        CustomDimensions.buildEventSettings: settings,
-      if (eventError != null)
-        CustomDimensions.buildEventError: eventError,
+      if (_command != null)
+        CustomDimensions.buildEventCommand: _command,
+      if (_settings != null)
+        CustomDimensions.buildEventSettings: _settings,
+      if (_eventError != null)
+        CustomDimensions.buildEventError: _eventError,
     });
     flutterUsage.sendEvent(
       category,
diff --git a/packages/flutter_tools/lib/src/reporting/usage.dart b/packages/flutter_tools/lib/src/reporting/usage.dart
index 125b511..da8fd86 100644
--- a/packages/flutter_tools/lib/src/reporting/usage.dart
+++ b/packages/flutter_tools/lib/src/reporting/usage.dart
@@ -83,6 +83,8 @@
                       analyticsIOFactory: analyticsIOFactory,
                       runningOnBot: runningOnBot);
 
+  factory Usage.test() => _DefaultUsage.test();
+
   /// Uses the global [Usage] instance to send a 'command' to analytics.
   static void command(String command, {
     Map<CustomDimensions, String> parameters,
@@ -265,6 +267,10 @@
     _analytics.analyticsOpt = AnalyticsOpt.optOut;
   }
 
+  _DefaultUsage.test() :
+      _suppressAnalytics = true,
+      _analytics = AnalyticsMock();
+
   Analytics _analytics;
 
   bool _printedWelcome = false;
diff --git a/packages/flutter_tools/test/general.shard/base/build_test.dart b/packages/flutter_tools/test/general.shard/base/build_test.dart
index 00a4625..e85e295 100644
--- a/packages/flutter_tools/test/general.shard/base/build_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/build_test.dart
@@ -13,6 +13,7 @@
 import 'package:flutter_tools/src/base/build.dart';
 import 'package:flutter_tools/src/ios/xcodeproj.dart';
 import 'package:flutter_tools/src/macos/xcode.dart';
+import 'package:flutter_tools/src/reporting/reporting.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -189,6 +190,7 @@
             logger: logger,
             fileSystem: fileSystem,
             terminal: Terminal.test(),
+            usage: Usage.test(),
           ),
         ),
         artifacts: mockArtifacts,
diff --git a/packages/flutter_tools/test/general.shard/ios/fallback_discovery_test.dart b/packages/flutter_tools/test/general.shard/ios/fallback_discovery_test.dart
index 0507795..f255299 100644
--- a/packages/flutter_tools/test/general.shard/ios/fallback_discovery_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/fallback_discovery_test.dart
@@ -8,15 +8,14 @@
 import 'package:flutter_tools/src/ios/fallback_discovery.dart';
 import 'package:flutter_tools/src/mdns_discovery.dart';
 import 'package:flutter_tools/src/protocol_discovery.dart';
+import 'package:flutter_tools/src/reporting/reporting.dart';
 import 'package:mockito/mockito.dart';
 import 'package:platform/platform.dart';
 import 'package:vm_service/vm_service.dart';
 
 import '../../src/common.dart';
-import '../../src/context.dart';
 import '../../src/mocks.dart';
 
-// This test still uses `testUsingContext` due to analytics usage.
 void main() {
   BufferLogger logger;
   FallbackDiscovery fallbackDiscovery;
@@ -39,6 +38,7 @@
       mDnsObservatoryDiscovery: mockMDnsObservatoryDiscovery,
       portForwarder: mockPortForwarder,
       protocolDiscovery: mockPrototcolDiscovery,
+      flutterUsage: Usage.test(),
       vmServiceConnectUri: (String uri, {Log log}) async {
         return mockVmService;
       },
@@ -47,7 +47,7 @@
       .thenAnswer((Invocation invocation) async => 1);
   });
 
-  testUsingContext('Selects assumed port if VM service connection is successful', () async {
+  testWithoutContext('Selects assumed port if VM service connection is successful', () async {
     when(mockVmService.getVM()).thenAnswer((Invocation invocation) async {
       return VM.parse(<String, Object>{})..isolates = <IsolateRef>[
         IsolateRef.parse(<String, Object>{}),
@@ -68,7 +68,7 @@
     ), Uri.parse('http://localhost:1'));
   });
 
-  testUsingContext('Selects assumed port when another isolate has no root library', () async {
+  testWithoutContext('Selects assumed port when another isolate has no root library', () async {
     when(mockVmService.getVM()).thenAnswer((Invocation invocation) async {
       return VM.parse(<String, Object>{})..isolates = <IsolateRef>[
         IsolateRef.parse(<String, Object>{})..id = '1',
@@ -93,7 +93,7 @@
     ), Uri.parse('http://localhost:1'));
   });
 
-  testUsingContext('Selects mdns discovery if VM service connecton fails due to Sentinel', () async {
+  testWithoutContext('Selects mdns discovery if VM service connecton fails due to Sentinel', () async {
     when(mockVmService.getVM()).thenAnswer((Invocation invocation) async {
       return VM.parse(<String, Object>{})..isolates = <IsolateRef>[
         IsolateRef(
@@ -124,7 +124,7 @@
     ), Uri.parse('http://localhost:1234'));
   });
 
-  testUsingContext('Selects mdns discovery if VM service connecton fails', () async {
+  testWithoutContext('Selects mdns discovery if VM service connecton fails', () async {
     when(mockVmService.getVM()).thenThrow(Exception());
 
     when(mockMDnsObservatoryDiscovery.getObservatoryUri(
@@ -146,7 +146,7 @@
     ), Uri.parse('http://localhost:1234'));
   });
 
-  testUsingContext('Selects log scanning if both VM Service and mDNS fails', () async {
+  testWithoutContext('Selects log scanning if both VM Service and mDNS fails', () async {
     when(mockVmService.getVM()).thenThrow(Exception());
     when(mockMDnsObservatoryDiscovery.getObservatoryUri(
       'hello',
diff --git a/packages/flutter_tools/test/general.shard/ios/mac_test.dart b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
index c8bcd36..727b25c 100644
--- a/packages/flutter_tools/test/general.shard/ios/mac_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
@@ -132,7 +132,7 @@
         ),
       );
 
-      await diagnoseXcodeBuildFailure(buildResult);
+      await diagnoseXcodeBuildFailure(buildResult, mockUsage, logger);
       verify(mockUsage.sendEvent('build',
         any,
         label: 'xcode-bitcode-failure',
@@ -140,8 +140,6 @@
           cdKey(CustomDimensions.buildEventCommand): buildCommands.toString(),
           cdKey(CustomDimensions.buildEventSettings): buildSettings.toString(),
       })).called(1);
-    }, overrides: <Type, Generator>{
-      Usage: () => mockUsage,
     });
 
     testUsingContext('No provisioning profile shows message', () async {
@@ -210,9 +208,9 @@
         ),
       );
 
-      await diagnoseXcodeBuildFailure(buildResult);
+      await diagnoseXcodeBuildFailure(buildResult, mockUsage, logger);
       expect(
-        testLogger.errorText,
+        logger.errorText,
         contains("No Provisioning Profile was found for your project's Bundle Identifier or your \ndevice."),
       );
     }, overrides: noColorTerminalOverride);
@@ -291,9 +289,9 @@
         ),
       );
 
-      await diagnoseXcodeBuildFailure(buildResult);
+      await diagnoseXcodeBuildFailure(buildResult, mockUsage, logger);
       expect(
-        testLogger.errorText,
+        logger.errorText,
         contains('Building a deployable iOS app requires a selected Development Team with a \nProvisioning Profile.'),
       );
     }, overrides: noColorTerminalOverride);
@@ -328,9 +326,9 @@
         ),
       );
 
-      await diagnoseXcodeBuildFailure(buildResult);
+      await diagnoseXcodeBuildFailure(buildResult, mockUsage, logger);
       expect(
-        testLogger.errorText,
+        logger.errorText,
         contains('Your Xcode project requires migration.'),
       );
     }, overrides: noColorTerminalOverride);
@@ -365,9 +363,9 @@
         ),
       );
 
-      await diagnoseXcodeBuildFailure(buildResult);
+      await diagnoseXcodeBuildFailure(buildResult, mockUsage, logger);
       expect(
-        testLogger.errorText,
+        logger.errorText,
         contains('Your Xcode project requires migration.'),
       );
     }, overrides: noColorTerminalOverride);
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index 233e9d0..81944db 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -13,6 +13,7 @@
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/ios/xcodeproj.dart';
 import 'package:flutter_tools/src/project.dart';
+import 'package:flutter_tools/src/reporting/reporting.dart';
 
 import 'package:mockito/mockito.dart';
 import 'package:platform/platform.dart';
@@ -48,6 +49,7 @@
       platform: platform,
       processManager: processManager,
       terminal: terminal,
+      usage: null,
     );
   });
 
@@ -130,6 +132,7 @@
       platform: platform,
       processManager: processManager,
       terminal: terminal,
+      usage: Usage.test(),
     );
     fileSystem.file(xcodebuild).deleteSync();
 
@@ -261,6 +264,7 @@
       platform: platform,
       processManager: processManager,
       terminal: terminal,
+      usage: Usage.test(),
     );
 
     expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
@@ -282,6 +286,7 @@
       platform: platform,
       processManager: processManager,
       terminal: terminal,
+      usage: Usage.test(),
     );
 
     expect(