[flutter_tools] Remove context usage from status and clean up test cases (#48446)

diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart
index 6dbebee..e3a61a1 100644
--- a/packages/flutter_tools/lib/src/base/logger.dart
+++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:meta/meta.dart';
+import 'package:platform/platform.dart';
 
 import '../base/context.dart';
 import '../globals.dart' as globals;
@@ -21,6 +22,15 @@
 /// If not provided via injection, a default instance is provided.
 TimeoutConfiguration get timeoutConfiguration => context.get<TimeoutConfiguration>() ?? const TimeoutConfiguration();
 
+/// A factory for generating [Stopwatch] instances for [Status] instances.
+class StopwatchFactory {
+  /// const constructor so that subclasses may be const.
+  const StopwatchFactory();
+
+  /// Create a new [Stopwatch] instance.
+  Stopwatch createStopwatch() => Stopwatch();
+}
+
 class TimeoutConfiguration {
   const TimeoutConfiguration();
 
@@ -166,11 +176,15 @@
     @required Stdio stdio,
     @required OutputPreferences outputPreferences,
     @required TimeoutConfiguration timeoutConfiguration,
+    @required Platform platform,
+    StopwatchFactory stopwatchFactory = const StopwatchFactory(),
   })
     : _stdio = stdio,
       _terminal = terminal,
       _timeoutConfiguration = timeoutConfiguration,
-      _outputPreferences = outputPreferences;
+      _outputPreferences = outputPreferences,
+      _stopwatchFactory = stopwatchFactory,
+      _platform = platform;
 
   @override
   final AnsiTerminal _terminal;
@@ -179,6 +193,8 @@
   @override
   final TimeoutConfiguration _timeoutConfiguration;
   final Stdio _stdio;
+  final StopwatchFactory _stopwatchFactory;
+  final Platform _platform;
 
   Status _status;
 
@@ -273,7 +289,8 @@
       return SilentStatus(
         timeout: timeout,
         onFinish: _clearStatus,
-        timeoutConfiguration: _timeoutConfiguration
+        timeoutConfiguration: _timeoutConfiguration,
+        stopwatch: _stopwatchFactory.createStopwatch(),
       )..start();
     }
     if (supportsColor) {
@@ -285,6 +302,8 @@
         onFinish: _clearStatus,
         stdio: _stdio,
         timeoutConfiguration: _timeoutConfiguration,
+        platform: _platform,
+        stopwatch: _stopwatchFactory.createStopwatch(),
       )..start();
     } else {
       _status = SummaryStatus(
@@ -294,6 +313,7 @@
         onFinish: _clearStatus,
         stdio: _stdio,
         timeoutConfiguration: _timeoutConfiguration,
+        stopwatch: _stopwatchFactory.createStopwatch(),
       )..start();
     }
     return _status;
@@ -321,11 +341,15 @@
     @required Stdio stdio,
     @required OutputPreferences outputPreferences,
     @required TimeoutConfiguration timeoutConfiguration,
+    @required Platform platform,
+    StopwatchFactory stopwatchFactory = const StopwatchFactory(),
   }) : super(
       terminal: terminal,
       stdio: stdio,
       outputPreferences: outputPreferences,
       timeoutConfiguration: timeoutConfiguration,
+      stopwatchFactory: stopwatchFactory,
+      platform: platform,
     );
 
   @override
@@ -342,10 +366,12 @@
   BufferLogger({
     @required AnsiTerminal terminal,
     @required OutputPreferences outputPreferences,
-    TimeoutConfiguration timeoutConfiguration = const TimeoutConfiguration()
+    TimeoutConfiguration timeoutConfiguration = const TimeoutConfiguration(),
+    StopwatchFactory stopwatchFactory = const StopwatchFactory(),
   }) : _outputPreferences = outputPreferences,
        _terminal = terminal,
-       _timeoutConfiguration = timeoutConfiguration;
+       _timeoutConfiguration = timeoutConfiguration,
+       _stopwatchFactory = stopwatchFactory;
 
   @override
   final OutputPreferences _outputPreferences;
@@ -356,6 +382,8 @@
   @override
   final TimeoutConfiguration _timeoutConfiguration;
 
+  final StopwatchFactory _stopwatchFactory;
+
   @override
   bool get isVerbose => false;
 
@@ -437,7 +465,7 @@
     return SilentStatus(
       timeout: timeout,
       timeoutConfiguration: _timeoutConfiguration,
-
+      stopwatch: _stopwatchFactory.createStopwatch(),
     )..start();
   }
 
@@ -453,8 +481,10 @@
 }
 
 class VerboseLogger extends Logger {
-  VerboseLogger(this.parent,  { @required Stopwatch stopwatch }) :
-    _stopwatch = stopwatch ?? context.get<Stopwatch>() ??  Stopwatch() {
+  VerboseLogger(this.parent,  {
+    StopwatchFactory stopwatchFactory = const StopwatchFactory()
+  }) : _stopwatch = stopwatchFactory.createStopwatch(),
+       _stopwatchFactory = stopwatchFactory {
     _stopwatch.start();
   }
 
@@ -471,6 +501,8 @@
   @override
   TimeoutConfiguration get _timeoutConfiguration => parent._timeoutConfiguration;
 
+  final StopwatchFactory _stopwatchFactory;
+
   @override
   bool get isVerbose => true;
 
@@ -529,10 +561,12 @@
   }) {
     assert(progressIndicatorPadding != null);
     printStatus(message);
-    final Stopwatch timer = Stopwatch()..start();
+    final Stopwatch timer = _stopwatchFactory.createStopwatch()..start();
     return SilentStatus(
       timeout: timeout,
       timeoutConfiguration: _timeoutConfiguration,
+      // This is intentionally a different stopwatch than above.
+      stopwatch: _stopwatchFactory.createStopwatch(),
       onFinish: () {
         String time;
         if (timeout == null || timeout > _timeoutConfiguration.fastOperation) {
@@ -623,28 +657,36 @@
     @required this.timeout,
     @required TimeoutConfiguration timeoutConfiguration,
     this.onFinish,
-  }) : _timeoutConfiguration = timeoutConfiguration;
+    @required Stopwatch stopwatch,
+  }) : _timeoutConfiguration = timeoutConfiguration,
+       _stopwatch = stopwatch;
 
   /// A [SilentStatus] or an [AnsiSpinner] (depending on whether the
   /// terminal is fancy enough), already started.
   factory Status.withSpinner({
     @required Duration timeout,
     @required TimeoutConfiguration timeoutConfiguration,
+    @required Stopwatch stopwatch,
+    @required bool supportsColor,
+    @required Platform platform,
     VoidCallback onFinish,
     SlowWarningCallback slowWarningCallback,
   }) {
-    if (globals.terminal.supportsColor) {
+    if (supportsColor) {
       return AnsiSpinner(
         timeout: timeout,
         onFinish: onFinish,
         slowWarningCallback: slowWarningCallback,
         timeoutConfiguration: timeoutConfiguration,
+        stopwatch: stopwatch,
+        platform: platform,
       )..start();
     }
     return SilentStatus(
       timeout: timeout,
       onFinish: onFinish,
       timeoutConfiguration: timeoutConfiguration,
+      stopwatch: stopwatch,
     )..start();
   }
 
@@ -653,7 +695,7 @@
   final TimeoutConfiguration _timeoutConfiguration;
 
   @protected
-  final Stopwatch _stopwatch = context.get<Stopwatch>() ?? Stopwatch();
+  final Stopwatch _stopwatch;
 
   @protected
   @visibleForTesting
@@ -704,11 +746,13 @@
   SilentStatus({
     @required Duration timeout,
     @required TimeoutConfiguration timeoutConfiguration,
+    @required Stopwatch stopwatch,
     VoidCallback onFinish,
   }) : super(
     timeout: timeout,
     onFinish: onFinish,
     timeoutConfiguration: timeoutConfiguration,
+    stopwatch: stopwatch,
   );
 }
 
@@ -718,14 +762,20 @@
   SummaryStatus({
     this.message = '',
     @required Duration timeout,
+    @required TimeoutConfiguration timeoutConfiguration,
+    @required Stopwatch stopwatch,
     this.padding = kDefaultStatusPadding,
     VoidCallback onFinish,
     Stdio stdio,
-    @required TimeoutConfiguration timeoutConfiguration,
   }) : assert(message != null),
        assert(padding != null),
        _stdio = stdio ?? globals.stdio,
-       super(timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration);
+       super(
+         timeout: timeout,
+         onFinish: onFinish,
+         timeoutConfiguration: timeoutConfiguration,
+         stopwatch: stopwatch,
+        );
 
   final String message;
   final int padding;
@@ -794,16 +844,25 @@
 class AnsiSpinner extends Status {
   AnsiSpinner({
     @required Duration timeout,
+    @required TimeoutConfiguration timeoutConfiguration,
+    @required Stopwatch stopwatch,
+    @required Platform platform,
     VoidCallback onFinish,
     this.slowWarningCallback,
     Stdio stdio,
-    @required TimeoutConfiguration timeoutConfiguration,
   }) : _stdio = stdio ?? globals.stdio,
-       super(timeout: timeout, onFinish: onFinish, timeoutConfiguration: timeoutConfiguration);
+       _isWindows = platform.isWindows,
+       super(
+         timeout: timeout,
+         onFinish: onFinish,
+         timeoutConfiguration: timeoutConfiguration,
+         stopwatch: stopwatch,
+        );
 
   final String _backspaceChar = '\b';
   final String _clearChar = ' ';
   final Stdio _stdio;
+  final bool _isWindows;
 
   bool timedOut = false;
 
@@ -811,9 +870,9 @@
   Timer timer;
 
   // Windows console font has a limited set of Unicode characters.
-  List<String> get _animation => globals.platform.isWindows
-      ? <String>[r'-', r'\', r'|', r'/']
-      : <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
+  List<String> get _animation => _isWindows
+      ? const <String>[r'-', r'\', r'|', r'/']
+      : const <String>['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
 
   static const String _defaultSlowWarning = '(This is taking an unexpectedly long time.)';
   final SlowWarningCallback slowWarningCallback;
@@ -903,16 +962,25 @@
 class AnsiStatus extends AnsiSpinner {
   AnsiStatus({
     this.message = '',
-    @required Duration timeout,
     this.multilineOutput = false,
     this.padding = kDefaultStatusPadding,
+    @required Duration timeout,
+    @required Stopwatch stopwatch,
+    @required Platform platform,
     VoidCallback onFinish,
     Stdio stdio,
     TimeoutConfiguration timeoutConfiguration,
   }) : assert(message != null),
        assert(multilineOutput != null),
        assert(padding != null),
-       super(timeout: timeout, onFinish: onFinish, stdio: stdio, timeoutConfiguration: timeoutConfiguration);
+       super(
+         timeout: timeout,
+         onFinish: onFinish,
+         stdio: stdio,
+         timeoutConfiguration: timeoutConfiguration,
+         stopwatch: stopwatch,
+         platform: platform,
+        );
 
   final String message;
   final bool multilineOutput;
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index b33a963..b03f056 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -974,7 +974,11 @@
   }) {
     assert(timeout != null);
     printStatus(message);
-    return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration);
+    return SilentStatus(
+      timeout: timeout,
+      timeoutConfiguration: timeoutConfiguration,
+      stopwatch: Stopwatch(),
+    );
   }
 
   void dispose() {
@@ -1181,7 +1185,7 @@
           'progressId': progressId,
           'finished': true,
         });
-      })..start();
+      }, stopwatch: Stopwatch())..start();
     return _status;
   }
 
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 92d6ba5..a6e7e5b 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -108,12 +108,14 @@
             stdio: globals.stdio,
             outputPreferences: outputPreferences,
             timeoutConfiguration: timeoutConfiguration,
+            platform: globals.platform,
           )
         : StdoutLogger(
             terminal: globals.terminal,
             stdio: globals.stdio,
             outputPreferences: outputPreferences,
             timeoutConfiguration: timeoutConfiguration,
+            platform: globals.platform,
           ),
       MacOSWorkflow: () => const MacOSWorkflow(),
       MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index a7cd3ec..cd7afb8 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -259,6 +259,9 @@
         timeout: timeoutConfiguration.fastOperation,
         slowWarningCallback: () => validator.slowWarning,
         timeoutConfiguration: timeoutConfiguration,
+        stopwatch: Stopwatch(),
+        supportsColor: globals.terminal.supportsColor,
+        platform: globals.platform,
       );
       ValidationResult result;
       try {
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 7b4203d..b3c7f74 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -285,6 +285,9 @@
     final Status status = Status.withSpinner(
       timeout: timeoutConfiguration.fastOperation,
       timeoutConfiguration: timeoutConfiguration,
+      platform: globals.platform,
+      stopwatch: Stopwatch(),
+      supportsColor: globals.terminal.supportsColor,
     );
     final List<String> showBuildSettingsCommand = <String>[
       _executable,
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
index ee6d56a..511de9a 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -239,7 +239,7 @@
     // Check for verbose.
     if (topLevelResults['verbose'] as bool) {
       // Override the logger.
-      contextOverrides[Logger] = VerboseLogger(globals.logger, stopwatch: Stopwatch());
+      contextOverrides[Logger] = VerboseLogger(globals.logger);
     }
 
     // Don't set wrapColumns unless the user said to: if it's set, then all
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
index 8e589ab..c51c372 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -704,7 +704,11 @@
     int progressIndicatorPadding = kDefaultStatusPadding,
   }) {
     _log('[progress] $message');
-    return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration)..start();
+    return SilentStatus(
+      timeout: timeout,
+      timeoutConfiguration: timeoutConfiguration,
+      stopwatch: Stopwatch(),
+    )..start();
   }
 
   bool _interrupt = false;
diff --git a/packages/flutter_tools/test/general.shard/base/logger_test.dart b/packages/flutter_tools/test/general.shard/base/logger_test.dart
index 7095381..3b15509 100644
--- a/packages/flutter_tools/test/general.shard/base/logger_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/logger_test.dart
@@ -5,24 +5,20 @@
 import 'dart:convert' show jsonEncode;
 
 import 'package:platform/platform.dart';
-import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
-import 'package:flutter_tools/src/globals.dart' as globals;
 import 'package:quiver/testing/async.dart';
 
 import '../../src/common.dart';
-import '../../src/context.dart';
 import '../../src/mocks.dart';
 
 final Platform _kNoAnsiPlatform = FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false;
+final String red = RegExp.escape(AnsiTerminal.red);
+final String bold = RegExp.escape(AnsiTerminal.bold);
+final String resetBold = RegExp.escape(AnsiTerminal.resetBold);
+final String resetColor = RegExp.escape(AnsiTerminal.resetColor);
 
 void main() {
-  final String red = RegExp.escape(AnsiTerminal.red);
-  final String bold = RegExp.escape(AnsiTerminal.bold);
-  final String resetBold = RegExp.escape(AnsiTerminal.resetBold);
-  final String resetColor = RegExp.escape(AnsiTerminal.resetColor);
-
   group('AppContext', () {
     FakeStopwatch fakeStopWatch;
 
@@ -37,7 +33,10 @@
         ),
         outputPreferences: OutputPreferences.test(showColor: false),
       );
-      final VerboseLogger verboseLogger = VerboseLogger(mockLogger, stopwatch: fakeStopWatch);
+      final VerboseLogger verboseLogger = VerboseLogger(
+        mockLogger,
+        stopwatchFactory: FakeStopwatchFactory(fakeStopWatch),
+      );
 
       verboseLogger.printStatus('Hey Hey Hey Hey');
       verboseLogger.printTrace('Oooh, I do I do I do');
@@ -57,7 +56,9 @@
         ),
         outputPreferences: OutputPreferences.test(showColor: true),
       );
-      final VerboseLogger verboseLogger = VerboseLogger(mockLogger, stopwatch: fakeStopWatch);
+      final VerboseLogger verboseLogger = VerboseLogger(
+        mockLogger, stopwatchFactory: FakeStopwatchFactory(fakeStopWatch),
+      );
 
       verboseLogger.printStatus('Hey Hey Hey Hey');
       verboseLogger.printTrace('Oooh, I do I do I do');
@@ -77,25 +78,16 @@
   group('Spinners', () {
     MockStdio mockStdio;
     FakeStopwatch mockStopwatch;
+    FakeStopwatchFactory stopwatchFactory;
     int called;
     const List<String> testPlatforms = <String>['linux', 'macos', 'windows', 'fuchsia'];
     final RegExp secondDigits = RegExp(r'[0-9,.]*[0-9]m?s');
 
-    AnsiStatus _createAnsiStatus() {
-      return AnsiStatus(
-        message: 'Hello world',
-        timeout: const Duration(seconds: 2),
-        padding: 20,
-        onFinish: () => called += 1,
-        stdio: mockStdio,
-        timeoutConfiguration: const TimeoutConfiguration(),
-      );
-    }
-
     setUp(() {
       mockStopwatch = FakeStopwatch();
       mockStdio = MockStdio();
       called = 0;
+      stopwatchFactory = FakeStopwatchFactory(mockStopwatch);
     });
 
     List<String> outputStdout() => mockStdio.writtenToStdout.join('').split('\n');
@@ -109,7 +101,21 @@
     }
 
     for (final String testOs in testPlatforms) {
-      testUsingContext('AnsiSpinner works for $testOs (1)', () async {
+      Platform currentPlatform() => FakePlatform(operatingSystem: testOs);
+
+      AnsiStatus createAnsiStatus() {
+        return AnsiStatus(
+          message: 'Hello world',
+          timeout: const Duration(seconds: 2),
+          padding: 20,
+          onFinish: () => called += 1,
+          stdio: mockStdio,
+          timeoutConfiguration: const TimeoutConfiguration(),
+          stopwatch: stopwatchFactory.createStopwatch(),
+          platform: currentPlatform(),
+        );
+      }
+      testWithoutContext('AnsiSpinner works for $testOs (1)', () async {
         bool done = false;
         mockStopwatch = FakeStopwatch();
         FakeAsync().run((FakeAsync time) {
@@ -117,38 +123,35 @@
             timeout: const Duration(hours: 10),
             stdio: mockStdio,
             timeoutConfiguration: const TimeoutConfiguration(),
+            stopwatch: stopwatchFactory.createStopwatch(),
+            platform: currentPlatform(),
           )..start();
           doWhileAsync(time, () => ansiSpinner.ticks < 10);
           List<String> lines = outputStdout();
           expect(lines[0], startsWith(
-            globals.platform.isWindows
+            currentPlatform().isWindows
               ? ' \b\\\b|\b/\b-\b\\\b|\b/\b-'
               : ' \b⣽\b⣻\b⢿\b⡿\b⣟\b⣯\b⣷\b⣾\b⣽\b⣻'
             ),
           );
           expect(lines[0].endsWith('\n'), isFalse);
           expect(lines.length, equals(1));
+
           ansiSpinner.stop();
           lines = outputStdout();
+
           expect(lines[0], endsWith('\b \b'));
           expect(lines.length, equals(1));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(() {
-            ansiSpinner.stop();
-          }, throwsA(isInstanceOf<AssertionError>()));
-          expect(() {
-            ansiSpinner.cancel();
-          }, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiSpinner.stop, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiSpinner.cancel, throwsA(isInstanceOf<AssertionError>()));
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Platform: () => FakePlatform(operatingSystem: testOs),
-        Stopwatch: () => mockStopwatch,
       });
 
-      testUsingContext('AnsiSpinner works for $testOs (2)', () async {
+      testWithoutContext('AnsiSpinner works for $testOs (2)', () async {
         bool done = false;
         mockStopwatch = FakeStopwatch();
         FakeAsync().run((FakeAsync time) {
@@ -156,13 +159,17 @@
             timeout: const Duration(seconds: 2),
             stdio: mockStdio,
             timeoutConfiguration: const TimeoutConfiguration(),
+            stopwatch: mockStopwatch,
+            platform: FakePlatform(operatingSystem: testOs),
           )..start();
           mockStopwatch.elapsed = const Duration(seconds: 1);
           doWhileAsync(time, () => ansiSpinner.ticks < 10); // one second
+
           expect(ansiSpinner.seemsSlow, isFalse);
           expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.')));
           mockStopwatch.elapsed = const Duration(seconds: 3);
           doWhileAsync(time, () => ansiSpinner.ticks < 30); // three seconds
+
           expect(ansiSpinner.seemsSlow, isTrue);
           // Check the 2nd line to verify there's a newline before the warning
           expect(outputStdout()[1], contains('This is taking an unexpectedly long time.'));
@@ -171,13 +178,9 @@
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Platform: () => FakePlatform(operatingSystem: testOs),
-        Stopwatch: () => mockStopwatch,
       });
 
-      // Uses Stopwatch from context.
-      testUsingContext('Stdout startProgress on colored terminal for $testOs', () async {
+      testWithoutContext('Stdout startProgress on colored terminal for $testOs', () async {
         bool done = false;
         FakeAsync().run((FakeAsync time) {
           final Logger logger = StdoutLogger(
@@ -188,27 +191,31 @@
             stdio: mockStdio,
             outputPreferences: OutputPreferences.test(showColor: true),
             timeoutConfiguration: const TimeoutConfiguration(),
+            stopwatchFactory: stopwatchFactory,
+            platform: currentPlatform(),
           );
           final Status status = logger.startProgress(
             'Hello',
             progressId: null,
-            timeout: timeoutConfiguration.slowOperation,
+            timeout: const TimeoutConfiguration().slowOperation,
             progressIndicatorPadding: 20, // this minus the "Hello" equals the 15 below.
           );
           expect(outputStderr().length, equals(1));
           expect(outputStderr().first, isEmpty);
           // the 5 below is the margin that is always included between the message and the time.
-          expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\$' :
-                                                                         r'^Hello {15} {5} {8}[\b]{8} {7}⣽$'));
+          expect(outputStdout().join('\n'),
+            matches(currentPlatform().isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\$' :
+                                                  r'^Hello {15} {5} {8}[\b]{8} {7}⣽$'));
           status.stop();
-          expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$' :
-                                                                         r'^Hello {15} {5} {8}[\b]{8} {7}⣽[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$'));
+          expect(outputStdout().join('\n'),
+            matches(currentPlatform().isWindows ? r'^Hello {15} {5} {8}[\b]{8} {7}\\[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$' :
+                                                  r'^Hello {15} {5} {8}[\b]{8} {7}⣽[\b]{8} {8}[\b]{8}[\d, ]{4}[\d]\.[\d]s[\n]$'));
           done = true;
         });
         expect(done, isTrue);
       });
 
-      testUsingContext('Stdout startProgress on colored terminal pauses on $testOs', () async {
+      testWithoutContext('Stdout startProgress on colored terminal pauses on $testOs', () async {
         bool done = false;
         FakeAsync().run((FakeAsync time) {
           mockStopwatch.elapsed = const Duration(seconds: 5);
@@ -220,6 +227,8 @@
             stdio: mockStdio,
             outputPreferences: OutputPreferences.test(showColor: true),
             timeoutConfiguration: const TimeoutConfiguration(),
+            stopwatchFactory: stopwatchFactory,
+            platform: currentPlatform(),
           );
           final Status status = logger.startProgress(
             'Knock Knock, Who\'s There',
@@ -228,8 +237,9 @@
           );
           logger.printStatus('Rude Interrupting Cow');
           status.stop();
-          final String a = globals.platform.isWindows ? '\\' : '⣽';
-          final String b = globals.platform.isWindows ? '|' : '⣻';
+          final String a = currentPlatform().isWindows ? '\\' : '⣽';
+          final String b = currentPlatform().isWindows ? '|' : '⣻';
+
           expect(
             outputStdout().join('\n'),
             'Knock Knock, Who\'s There     ' // initial message
@@ -250,22 +260,22 @@
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Stopwatch: () => mockStopwatch,
       });
 
-      testUsingContext('AnsiStatus works for $testOs', () {
-        final AnsiStatus ansiStatus = _createAnsiStatus();
+      testWithoutContext('AnsiStatus works for $testOs', () {
+        final AnsiStatus ansiStatus = createAnsiStatus();
         bool done = false;
         FakeAsync().run((FakeAsync time) {
           ansiStatus.start();
           mockStopwatch.elapsed = const Duration(seconds: 1);
           doWhileAsync(time, () => ansiStatus.ticks < 10); // one second
+
           expect(ansiStatus.seemsSlow, isFalse);
           expect(outputStdout().join('\n'), isNot(contains('This is taking an unexpectedly long time.')));
           expect(outputStdout().join('\n'), isNot(contains('(!)')));
           mockStopwatch.elapsed = const Duration(seconds: 3);
           doWhileAsync(time, () => ansiStatus.ticks < 30); // three seconds
+
           expect(ansiStatus.seemsSlow, isTrue);
           expect(outputStdout().join('\n'), contains('This is taking an unexpectedly long time.'));
 
@@ -283,20 +293,18 @@
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Platform: () => FakePlatform(operatingSystem: testOs),
-        Stopwatch: () => mockStopwatch,
       });
 
-      testUsingContext('AnsiStatus works when canceled for $testOs', () async {
-        final AnsiStatus ansiStatus = _createAnsiStatus();
+      testWithoutContext('AnsiStatus works when canceled for $testOs', () async {
+        final AnsiStatus ansiStatus = createAnsiStatus();
         bool done = false;
         FakeAsync().run((FakeAsync time) {
           ansiStatus.start();
           mockStopwatch.elapsed = const Duration(seconds: 1);
           doWhileAsync(time, () => ansiStatus.ticks < 10);
           List<String> lines = outputStdout();
-          expect(lines[0], startsWith(globals.platform.isWindows
+
+          expect(lines[0], startsWith(testOs == 'windows'
               ? 'Hello world                      \b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |\b\b\b\b\b\b\b\b       /\b\b\b\b\b\b\b\b       -\b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |\b\b\b\b\b\b\b\b       /\b\b\b\b\b\b\b\b       -\b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |'
               : 'Hello world                      \b\b\b\b\b\b\b\b       ⣽\b\b\b\b\b\b\b\b       ⣻\b\b\b\b\b\b\b\b       ⢿\b\b\b\b\b\b\b\b       ⡿\b\b\b\b\b\b\b\b       ⣟\b\b\b\b\b\b\b\b       ⣯\b\b\b\b\b\b\b\b       ⣷\b\b\b\b\b\b\b\b       ⣾\b\b\b\b\b\b\b\b       ⣽\b\b\b\b\b\b\b\b       ⣻'));
           expect(lines.length, equals(1));
@@ -307,8 +315,9 @@
           lines = outputStdout();
           final List<Match> matches = secondDigits.allMatches(lines[0]).toList();
           expect(matches, isEmpty);
-          final String x = globals.platform.isWindows ? '|' : '⣻';
-          expect(lines[0], endsWith('$x\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b\b'));
+          final String leading = currentPlatform().isWindows ? '|' : '⣻';
+
+          expect(lines[0], endsWith('$leading\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b\b'));
           expect(called, equals(1));
           expect(lines.length, equals(2));
           expect(lines[1], equals(''));
@@ -319,22 +328,20 @@
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Platform: () => FakePlatform(operatingSystem: testOs),
-        Stopwatch: () => mockStopwatch,
       });
 
-      testUsingContext('AnsiStatus works when stopped for $testOs', () async {
-        final AnsiStatus ansiStatus = _createAnsiStatus();
+      testWithoutContext('AnsiStatus works when stopped for $testOs', () async {
+        final AnsiStatus ansiStatus = createAnsiStatus();
         bool done = false;
         FakeAsync().run((FakeAsync time) {
           ansiStatus.start();
           mockStopwatch.elapsed = const Duration(seconds: 1);
           doWhileAsync(time, () => ansiStatus.ticks < 10);
           List<String> lines = outputStdout();
+
           expect(lines, hasLength(1));
           expect(lines[0],
-            globals.platform.isWindows
+            currentPlatform().isWindows
               ? 'Hello world                      \b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |\b\b\b\b\b\b\b\b       /\b\b\b\b\b\b\b\b       -\b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |\b\b\b\b\b\b\b\b       /\b\b\b\b\b\b\b\b       -\b\b\b\b\b\b\b\b       \\\b\b\b\b\b\b\b\b       |'
               : 'Hello world                      \b\b\b\b\b\b\b\b       ⣽\b\b\b\b\b\b\b\b       ⣻\b\b\b\b\b\b\b\b       ⢿\b\b\b\b\b\b\b\b       ⡿\b\b\b\b\b\b\b\b       ⣟\b\b\b\b\b\b\b\b       ⣯\b\b\b\b\b\b\b\b       ⣷\b\b\b\b\b\b\b\b       ⣾\b\b\b\b\b\b\b\b       ⣽\b\b\b\b\b\b\b\b       ⣻',
           );
@@ -344,7 +351,7 @@
           lines = outputStdout();
           expect(lines, hasLength(2));
           expect(lines[0], matches(
-            globals.platform.isWindows
+            currentPlatform().isWindows
               ? r'Hello world               {8}[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7}/[\b]{8} {7}-[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7}/[\b]{8} {7}-[\b]{8} {7}\\[\b]{8} {7}|[\b]{8} {7} [\b]{8}[\d., ]{6}[\d]ms$'
               : r'Hello world               {8}[\b]{8} {7}⣽[\b]{8} {7}⣻[\b]{8} {7}⢿[\b]{8} {7}⡿[\b]{8} {7}⣟[\b]{8} {7}⣯[\b]{8} {7}⣷[\b]{8} {7}⣾[\b]{8} {7}⣽[\b]{8} {7}⣻[\b]{8} {7} [\b]{8}[\d., ]{5}[\d]ms$'
           ));
@@ -353,20 +360,18 @@
           expect(times, isNotNull);
           expect(times, hasLength(1));
           final Match match = times.single;
+
           expect(lines[0], endsWith(match.group(0)));
           expect(called, equals(1));
           expect(lines.length, equals(2));
           expect(lines[1], equals(''));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(() { ansiStatus.stop(); }, throwsA(isInstanceOf<AssertionError>()));
-          expect(() { ansiStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiStatus.stop, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
           done = true;
         });
         expect(done, isTrue);
-      }, overrides: <Type, Generator>{
-        Platform: () => FakePlatform(operatingSystem: testOs),
-        Stopwatch: () => mockStopwatch,
       });
     }
   });
@@ -381,11 +386,12 @@
       called = 0;
       summaryStatus = SummaryStatus(
         message: 'Hello world',
-        timeout: timeoutConfiguration.slowOperation,
+        timeout: const TimeoutConfiguration().slowOperation,
         padding: 20,
         onFinish: () => called++,
         stdio: mockStdio,
         timeoutConfiguration: const TimeoutConfiguration(),
+        stopwatch: FakeStopwatch(),
       );
     });
 
@@ -401,6 +407,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printError('0123456789' * 15);
       final List<String> lines = outputStderr();
@@ -422,6 +429,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printError('0123456789' * 15, indent: 5);
       final List<String> lines = outputStderr();
@@ -446,6 +454,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printError('0123456789' * 15, hangingIndent: 5);
       final List<String> lines = outputStderr();
@@ -470,6 +479,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printError('0123456789' * 15, indent: 4, hangingIndent: 5);
       final List<String> lines = outputStderr();
@@ -494,6 +504,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus('0123456789' * 15);
       final List<String> lines = outputStdout();
@@ -515,6 +526,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus('0123456789' * 15, indent: 5);
       final List<String> lines = outputStdout();
@@ -539,6 +551,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus('0123456789' * 15, hangingIndent: 5);
       final List<String> lines = outputStdout();
@@ -554,7 +567,7 @@
       expect(lines[5], isEmpty);
     });
 
-    testUsingContext('Stdout logs are wrapped, indented, and can have hanging indent.', () async {
+    testWithoutContext('Stdout logs are wrapped, indented, and can have hanging indent.', () async {
       final Logger logger = StdoutLogger(
         terminal: AnsiTerminal(
           stdio: mockStdio,
@@ -563,6 +576,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40, showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus('0123456789' * 15, indent: 4, hangingIndent: 5);
       final List<String> lines = outputStdout();
@@ -587,6 +601,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(showColor: true),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printError('Pants on fire!');
       final List<String> lines = outputStderr();
@@ -605,6 +620,7 @@
         stdio: mockStdio,
         outputPreferences:  OutputPreferences.test(showColor: true),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus('All good.');
 
@@ -623,6 +639,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(showColor: true),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus(
         null,
@@ -647,6 +664,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.printStatus(
         null,
@@ -661,8 +679,7 @@
       expect(lines[0], equals(''));
     });
 
-    // Status uses Stopwatch from context.
-    test('Stdout startProgress on non-color terminal', () async {
+    testWithoutContext('Stdout startProgress on non-color terminal', () async {
       bool done = false;
       FakeAsync().run((FakeAsync time) {
         final Logger logger = StdoutLogger(
@@ -673,6 +690,7 @@
           stdio: mockStdio,
           outputPreferences: OutputPreferences.test(showColor: false),
           timeoutConfiguration: const TimeoutConfiguration(),
+          platform: FakePlatform(),
         );
         final Status status = logger.startProgress(
           'Hello',
@@ -683,17 +701,24 @@
         expect(outputStderr().length, equals(1));
         expect(outputStderr().first, isEmpty);
         // the 5 below is the margin that is always included between the message and the time.
-        expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5}$' :
-                                                                       r'^Hello {15} {5}$'));
+        expect(outputStdout().join('\n'), matches(r'^Hello {15} {5}$'));
         status.stop();
-        expect(outputStdout().join('\n'), matches(globals.platform.isWindows ? r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$' :
-                                                                       r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$'));
+        expect(outputStdout().join('\n'), matches(r'^Hello {15} {5}[\d, ]{4}[\d]\.[\d]s[\n]$'));
         done = true;
       });
       expect(done, isTrue);
     });
 
-    testUsingContext('SummaryStatus works when canceled', () async {
+    testWithoutContext('SummaryStatus works when canceled', () async {
+      final SummaryStatus summaryStatus = SummaryStatus(
+        message: 'Hello world',
+        timeout: const TimeoutConfiguration().slowOperation,
+        padding: 20,
+        onFinish: () => called++,
+        stdio: mockStdio,
+        timeoutConfiguration: const TimeoutConfiguration(),
+        stopwatch: FakeStopwatch(),
+      );
       summaryStatus.start();
       List<String> lines = outputStdout();
       expect(lines[0], startsWith('Hello world              '));
@@ -711,13 +736,11 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(() { summaryStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>()));
-      expect(() { summaryStatus.stop(); }, throwsA(isInstanceOf<AssertionError>()));
-    }, overrides: <Type, Generator>{
-      Platform: () => _kNoAnsiPlatform,
+      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
     });
 
-    testUsingContext('SummaryStatus works when stopped', () async {
+    testWithoutContext('SummaryStatus works when stopped', () async {
       summaryStatus.start();
       List<String> lines = outputStdout();
       expect(lines[0], startsWith('Hello world              '));
@@ -736,16 +759,11 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(() { summaryStatus.stop(); }, throwsA(isInstanceOf<AssertionError>()));
-      expect(() { summaryStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>()));
-    }, overrides: <Type, Generator>{
-      Platform: () => _kNoAnsiPlatform,
+      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
     });
 
-    // Status still uses Stopwatch from context.
-    // TODO(jonahwilliams): switch to testWithoutContext once logger uses a
-    // TimerFactory.
-    test('sequential startProgress calls with StdoutLogger', () async {
+    testWithoutContext('sequential startProgress calls with StdoutLogger', () async {
       final Logger logger = StdoutLogger(
         terminal: AnsiTerminal(
           stdio: mockStdio,
@@ -754,6 +772,7 @@
         stdio: mockStdio,
         outputPreferences: OutputPreferences.test(showColor: false),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       );
       logger.startProgress('AAA', timeout: const TimeoutConfiguration().fastOperation)..stop();
       logger.startProgress('BBB', timeout: const TimeoutConfiguration().fastOperation)..stop();
@@ -768,8 +787,7 @@
       expect(output[1], matches(RegExp(r'BBB[ ]{61}[\d, ]{5}[\d]ms')));
     });
 
-    // Status still uses Stopwatch from context.
-    test('sequential startProgress calls with VerboseLogger and StdoutLogger', () async {
+    testWithoutContext('sequential startProgress calls with VerboseLogger and StdoutLogger', () async {
       final Logger logger = VerboseLogger(
         StdoutLogger(
           terminal: AnsiTerminal(
@@ -779,8 +797,9 @@
           stdio: mockStdio,
           outputPreferences: OutputPreferences.test(),
           timeoutConfiguration: const TimeoutConfiguration(),
+          platform: FakePlatform(),
         ),
-        stopwatch: FakeStopwatch(),
+        stopwatchFactory: FakeStopwatchFactory(),
       );
       logger.startProgress('AAA', timeout: const TimeoutConfiguration().fastOperation)..stop();
       logger.startProgress('BBB', timeout: const TimeoutConfiguration().fastOperation)..stop();
@@ -794,8 +813,7 @@
       ]);
     });
 
-    // Status still uses Stopwatch from context.
-    test('sequential startProgress calls with BufferLogger', () async {
+    testWithoutContext('sequential startProgress calls with BufferLogger', () async {
       final BufferLogger logger = BufferLogger(
         terminal: AnsiTerminal(
           stdio: mockStdio,
@@ -846,3 +864,14 @@
   @override
   String toString() => '$runtimeType $elapsed $isRunning';
 }
+
+class FakeStopwatchFactory implements StopwatchFactory {
+  FakeStopwatchFactory([this.stopwatch]);
+
+  Stopwatch stopwatch;
+
+  @override
+  Stopwatch createStopwatch() {
+    return stopwatch ?? FakeStopwatch();
+  }
+}
diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart
index 5e4fb07..f7ea226 100644
--- a/packages/flutter_tools/test/general.shard/vmservice_test.dart
+++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart
@@ -196,6 +196,7 @@
         stdio: mockStdio,
         terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       ),
       WebSocketConnector: () => (String url, {CompressionOptions compression}) async => throw const SocketException('test'),
     });
@@ -275,6 +276,7 @@
         terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
         stdio: mockStdio,
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       ),
     });
 
@@ -292,6 +294,7 @@
         terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
         stdio: mockStdio,
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       ),
     });
 
@@ -310,6 +313,7 @@
         terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
         stdio: mockStdio,
         timeoutConfiguration: const TimeoutConfiguration(),
+        platform: FakePlatform(),
       ),
     });
   });