[flutter_tools] Make OperatingSystemUtils context-free (#49740)

diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index 50fc605..c2a27e8 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -7,7 +7,6 @@
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/version.dart';
 import '../convert.dart';
@@ -51,7 +50,7 @@
   final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
 
   if (sdk?.latestVersion == null) {
-    return os.which('adb')?.path;
+    return globals.os.which('adb')?.path;
   } else {
     return sdk?.adbPath;
   }
@@ -331,7 +330,7 @@
       }
 
       // in build-tools/$version/aapt
-      final List<File> aaptBins = os.whichAll('aapt');
+      final List<File> aaptBins = globals.os.whichAll('aapt');
       for (File aaptBin in aaptBins) {
         // Make sure we're using the aapt from the SDK.
         aaptBin = globals.fs.file(aaptBin.resolveSymbolicLinksSync());
@@ -342,7 +341,7 @@
       }
 
       // in platform-tools/adb
-      final List<File> adbBins = os.whichAll('adb');
+      final List<File> adbBins = globals.os.whichAll('adb');
       for (File adbBin in adbBins) {
         // Make sure we're using the adb from the SDK.
         adbBin = globals.fs.file(adbBin.resolveSymbolicLinksSync());
@@ -566,7 +565,7 @@
     }
 
     // Fallback to PATH based lookup.
-    return os.which(_javaExecutable)?.path;
+    return globals.os.which(_javaExecutable)?.path;
   }
 
   Map<String, String> _sdkManagerEnv;
@@ -578,8 +577,9 @@
       _sdkManagerEnv = <String, String>{};
       final String javaBinary = findJavaBinary();
       if (javaBinary != null) {
-        _sdkManagerEnv['PATH'] =
-            globals.fs.path.dirname(javaBinary) + os.pathVarSeparator + globals.platform.environment['PATH'];
+        _sdkManagerEnv['PATH'] = globals.fs.path.dirname(javaBinary) +
+                                 globals.os.pathVarSeparator +
+                                 globals.platform.environment['PATH'];
       }
     }
     return _sdkManagerEnv;
diff --git a/packages/flutter_tools/lib/src/android/gradle_utils.dart b/packages/flutter_tools/lib/src/android/gradle_utils.dart
index 8e71ba0..42b6b43 100644
--- a/packages/flutter_tools/lib/src/android/gradle_utils.dart
+++ b/packages/flutter_tools/lib/src/android/gradle_utils.dart
@@ -8,7 +8,6 @@
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
-import '../base/os.dart';
 import '../base/terminal.dart';
 import '../base/utils.dart';
 import '../base/version.dart';
@@ -172,7 +171,7 @@
 void _giveExecutePermissionIfNeeded(File executable) {
   if (!_hasAllExecutableFlagSet(executable)) {
     globals.printTrace('Trying to give execute permission to ${executable.path}.');
-    os.makeExecutable(executable);
+    globals.os.makeExecutable(executable);
   }
 }
 
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart
index b8e7ab2..0c0448b 100644
--- a/packages/flutter_tools/lib/src/application_package.dart
+++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -14,7 +14,6 @@
 import 'base/context.dart';
 import 'base/file_system.dart';
 import 'base/io.dart';
-import 'base/os.dart' show os;
 import 'base/process.dart';
 import 'base/user_messages.dart';
 import 'build_info.dart';
@@ -291,7 +290,7 @@
       shutdownHooks.addShutdownHook(() async {
         await tempDir.delete(recursive: true);
       }, ShutdownStage.STILL_RECORDING);
-      os.unzip(globals.fs.file(applicationBinary), tempDir);
+      globals.os.unzip(globals.fs.file(applicationBinary), tempDir);
       final Directory payloadDir = globals.fs.directory(
         globals.fs.path.join(tempDir.path, 'Payload'),
       );
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart
index b0cd1d4..65c8b5a 100644
--- a/packages/flutter_tools/lib/src/base/os.dart
+++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -3,26 +3,60 @@
 // found in the LICENSE file.
 
 import 'package:archive/archive.dart';
+import 'package:file/file.dart';
+import 'package:meta/meta.dart';
+import 'package:platform/platform.dart';
+import 'package:process/process.dart';
 
 import '../globals.dart' as globals;
-import 'context.dart';
 import 'file_system.dart';
 import 'io.dart';
+import 'logger.dart';
 import 'process.dart';
 
-/// Returns [OperatingSystemUtils] active in the current app context (i.e. zone).
-OperatingSystemUtils get os => context.get<OperatingSystemUtils>();
-
 abstract class OperatingSystemUtils {
-  factory OperatingSystemUtils() {
-    if (globals.platform.isWindows) {
-      return _WindowsUtils();
+  factory OperatingSystemUtils({
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required Platform platform,
+    @required ProcessManager processManager,
+  }) {
+    if (platform.isWindows) {
+      return _WindowsUtils(
+        fileSystem: fileSystem,
+        logger: logger,
+        platform: platform,
+        processManager: processManager,
+      );
     } else {
-      return _PosixUtils();
+      return _PosixUtils(
+        fileSystem: fileSystem,
+        logger: logger,
+        platform: platform,
+        processManager: processManager,
+      );
     }
   }
 
-  OperatingSystemUtils._private();
+  OperatingSystemUtils._private({
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required Platform platform,
+    @required ProcessManager processManager,
+  }) : _fileSystem = fileSystem,
+       _logger = logger,
+       _platform = platform,
+       _processManager = processManager,
+       _processUtils = ProcessUtils(
+        logger: logger,
+        processManager: processManager,
+      );
+
+  final FileSystem _fileSystem;
+  final Logger _logger;
+  final Platform _platform;
+  final ProcessManager _processManager;
+  final ProcessUtils _processUtils;
 
   /// Make the given file executable. This may be a no-op on some platforms.
   void makeExecutable(File file);
@@ -73,7 +107,7 @@
       'linux': 'Linux',
       'windows': 'Windows',
     };
-    final String osName = globals.platform.operatingSystem;
+    final String osName = _platform.operatingSystem;
     return osNames.containsKey(osName) ? osNames[osName] : osName;
   }
 
@@ -101,10 +135,10 @@
       if (!ipv6) {
         return findFreePort(ipv6: true);
       }
-      globals.printTrace('findFreePort failed: $e');
+      _logger.printTrace('findFreePort failed: $e');
     } catch (e) {
       // Failures are signaled by a return value of 0 from this function.
-      globals.printTrace('findFreePort failed: $e');
+      _logger.printTrace('findFreePort failed: $e');
     } finally {
       if (serverSocket != null) {
         await serverSocket.close();
@@ -115,7 +149,17 @@
 }
 
 class _PosixUtils extends OperatingSystemUtils {
-  _PosixUtils() : super._private();
+  _PosixUtils({
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required Platform platform,
+    @required ProcessManager processManager,
+  }) : super._private(
+    fileSystem: fileSystem,
+    logger: logger,
+    platform: platform,
+    processManager: processManager,
+  );
 
   @override
   void makeExecutable(File file) {
@@ -125,16 +169,20 @@
   @override
   void chmod(FileSystemEntity entity, String mode) {
     try {
-      final ProcessResult result = globals.processManager.runSync(<String>['chmod', mode, entity.path]);
+      final ProcessResult result = _processManager.runSync(
+        <String>['chmod', mode, entity.path],
+      );
       if (result.exitCode != 0) {
-        globals.printTrace(
+        _logger.printTrace(
           'Error trying to run chmod on ${entity.absolute.path}'
           '\nstdout: ${result.stdout}'
           '\nstderr: ${result.stderr}',
         );
       }
     } on ProcessException catch (error) {
-      globals.printTrace('Error trying to run chmod on ${entity.absolute.path}: $error');
+      _logger.printTrace(
+        'Error trying to run chmod on ${entity.absolute.path}: $error',
+      );
     }
   }
 
@@ -145,17 +193,19 @@
       if (all) '-a',
       execName,
     ];
-    final ProcessResult result = globals.processManager.runSync(command);
+    final ProcessResult result = _processManager.runSync(command);
     if (result.exitCode != 0) {
       return const <File>[];
     }
     final String stdout = result.stdout as String;
-    return stdout.trim().split('\n').map<File>((String path) => globals.fs.file(path.trim())).toList();
+    return stdout.trim().split('\n').map<File>(
+      (String path) => _fileSystem.file(path.trim()),
+    ).toList();
   }
 
   @override
   void zip(Directory data, File zipFile) {
-    processUtils.runSync(
+    _processUtils.runSync(
       <String>['zip', '-r', '-q', zipFile.path, '.'],
       workingDirectory: data.path,
       throwOnError: true,
@@ -165,7 +215,7 @@
   // unzip -o -q zipfile -d dest
   @override
   void unzip(File file, Directory targetDirectory) {
-    processUtils.runSync(
+    _processUtils.runSync(
       <String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
       throwOnError: true,
     );
@@ -173,12 +223,12 @@
 
   @override
   bool verifyZip(File zipFile) =>
-      processUtils.exitsHappySync(<String>['zip', '-T', zipFile.path]);
+    _processUtils.exitsHappySync(<String>['zip', '-T', zipFile.path]);
 
   // tar -xzf tarball -C dest
   @override
   void unpack(File gzippedTarFile, Directory targetDirectory) {
-    processUtils.runSync(
+    _processUtils.runSync(
       <String>['tar', '-xzf', gzippedTarFile.path, '-C', targetDirectory.path],
       throwOnError: true,
     );
@@ -186,15 +236,15 @@
 
   @override
   bool verifyGzip(File gzippedFile) =>
-      processUtils.exitsHappySync(<String>['gzip', '-t', gzippedFile.path]);
+    _processUtils.exitsHappySync(<String>['gzip', '-t', gzippedFile.path]);
 
   @override
   File makePipe(String path) {
-    processUtils.runSync(
+    _processUtils.runSync(
       <String>['mkfifo', path],
       throwOnError: true,
     );
-    return globals.fs.file(path);
+    return _fileSystem.file(path);
   }
 
   String _name;
@@ -202,11 +252,11 @@
   @override
   String get name {
     if (_name == null) {
-      if (globals.platform.isMacOS) {
+      if (_platform.isMacOS) {
         final List<RunResult> results = <RunResult>[
-          processUtils.runSync(<String>['sw_vers', '-productName']),
-          processUtils.runSync(<String>['sw_vers', '-productVersion']),
-          processUtils.runSync(<String>['sw_vers', '-buildVersion']),
+          _processUtils.runSync(<String>['sw_vers', '-productName']),
+          _processUtils.runSync(<String>['sw_vers', '-productVersion']),
+          _processUtils.runSync(<String>['sw_vers', '-buildVersion']),
         ];
         if (results.every((RunResult result) => result.exitCode == 0)) {
           _name = '${results[0].stdout.trim()} ${results[1].stdout
@@ -223,7 +273,17 @@
 }
 
 class _WindowsUtils extends OperatingSystemUtils {
-  _WindowsUtils() : super._private();
+  _WindowsUtils({
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required Platform platform,
+    @required ProcessManager processManager,
+  }) : super._private(
+    fileSystem: fileSystem,
+    logger: logger,
+    platform: platform,
+    processManager: processManager,
+  );
 
   @override
   void makeExecutable(File file) {}
@@ -234,15 +294,15 @@
   @override
   List<File> _which(String execName, { bool all = false }) {
     // `where` always returns all matches, not just the first one.
-    final ProcessResult result = globals.processManager.runSync(<String>['where', execName]);
+    final ProcessResult result = _processManager.runSync(<String>['where', execName]);
     if (result.exitCode != 0) {
       return const <File>[];
     }
     final List<String> lines = (result.stdout as String).trim().split('\n');
     if (all) {
-      return lines.map<File>((String path) => globals.fs.file(path.trim())).toList();
+      return lines.map<File>((String path) => _fileSystem.file(path.trim())).toList();
     }
-    return <File>[globals.fs.file(lines.first.trim())];
+    return <File>[_fileSystem.file(lines.first.trim())];
   }
 
   @override
@@ -305,7 +365,10 @@
         continue;
       }
 
-      final File destFile = globals.fs.file(globals.fs.path.join(targetDirectory.path, archiveFile.name));
+      final File destFile = _fileSystem.file(_fileSystem.path.join(
+        targetDirectory.path,
+        archiveFile.name,
+      ));
       if (!destFile.parent.existsSync()) {
         destFile.parent.createSync(recursive: true);
       }
@@ -323,7 +386,7 @@
   @override
   String get name {
     if (_name == null) {
-      final ProcessResult result = globals.processManager.runSync(
+      final ProcessResult result = _processManager.runSync(
           <String>['ver'], runInShell: true);
       if (result.exitCode == 0) {
         _name = (result.stdout as String).trim();
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index a7dda4c..670b8c6 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -18,7 +18,6 @@
 import '../base/io.dart';
 import '../base/logger.dart';
 import '../base/net.dart';
-import '../base/os.dart';
 import '../base/terminal.dart';
 import '../base/utils.dart';
 import '../build_info.dart';
@@ -403,7 +402,7 @@
     );
     final String effectiveHostname = debuggingOptions.hostname ?? 'localhost';
     final int hostPort = debuggingOptions.port == null
-        ? await os.findFreePort()
+        ? await globals.os.findFreePort()
         : int.tryParse(debuggingOptions.port);
     device.devFS = WebDevFS(
       effectiveHostname,
diff --git a/packages/flutter_tools/lib/src/build_runner/web_fs.dart b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
index 0ae5847..aee81c6 100644
--- a/packages/flutter_tools/lib/src/build_runner/web_fs.dart
+++ b/packages/flutter_tools/lib/src/build_runner/web_fs.dart
@@ -27,7 +27,6 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/net.dart';
-import '../base/os.dart';
 import '../build_info.dart';
 import '../bundle.dart';
 import '../cache.dart';
@@ -225,7 +224,7 @@
 
     // Initialize the dwds server.
     final String effectiveHostname = hostname ?? _kHostName;
-    final int hostPort = port == null ? await os.findFreePort() : int.tryParse(port);
+    final int hostPort = port == null ? await globals.os.findFreePort() : int.tryParse(port);
 
     final Pipeline pipeline = const Pipeline().addMiddleware((Handler innerHandler) {
       return (Request request) async {
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index 7151899..c39411c 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -13,7 +13,7 @@
 import 'base/io.dart' show SocketException;
 import 'base/logger.dart';
 import 'base/net.dart';
-import 'base/os.dart';
+import 'base/os.dart' show OperatingSystemUtils;
 import 'base/process.dart';
 import 'features.dart';
 import 'globals.dart' as globals;
@@ -102,7 +102,7 @@
        _logger = logger ?? globals.logger,
        _fileSystem = fileSystem ?? globals.fs,
        _platform = platform ?? globals.platform ,
-       _osUtils = osUtils ?? os {
+       _osUtils = osUtils ?? globals.os {
     // TODO(zra): Move to initializer list once logger and platform parameters
     // are required.
     _net = Net(logger: _logger, platform: _platform);
@@ -600,12 +600,12 @@
 
   /// Download a zip archive from the given [url] and unzip it to [location].
   Future<void> _downloadZipArchive(String message, Uri url, Directory location) {
-    return _downloadArchive(message, url, location, os.verifyZip, os.unzip);
+    return _downloadArchive(message, url, location, globals.os.verifyZip, globals.os.unzip);
   }
 
   /// Download a gzipped tarball from the given [url] and unpack it to [location].
   Future<void> _downloadZippedTarball(String message, Uri url, Directory location) {
-    return _downloadArchive(message, url, location, os.verifyGzip, os.unpack);
+    return _downloadArchive(message, url, location, globals.os.verifyGzip, globals.os.unpack);
   }
 
   /// Create a temporary file and invoke [onTemporaryFile] with the file as
@@ -748,7 +748,7 @@
         if (frameworkZip.existsSync()) {
           final Directory framework = globals.fs.directory(globals.fs.path.join(dir.path, '$frameworkName.framework'));
           framework.createSync();
-          os.unzip(frameworkZip, framework);
+          globals.os.unzip(frameworkZip, framework);
         }
       }
     }
@@ -786,14 +786,14 @@
   }
 
   void _makeFilesExecutable(Directory dir) {
-    os.chmod(dir, 'a+r,a+x');
+    globals.os.chmod(dir, 'a+r,a+x');
     for (final FileSystemEntity entity in dir.listSync(recursive: true)) {
       if (entity is File) {
         final FileStat stat = entity.statSync();
         final bool isUserExecutable = ((stat.mode >> 6) & 0x1) == 1;
         if (entity.basename == 'flutter_tester' || isUserExecutable) {
           // Make the file readable and executable by all users.
-          os.chmod(entity, 'a+r,a+x');
+          globals.os.chmod(entity, 'a+r,a+x');
         }
       }
     }
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index b4fb338..ea11e67 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -15,7 +15,6 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/net.dart';
-import '../base/os.dart';
 import '../base/utils.dart';
 import '../cache.dart';
 import '../convert.dart';
@@ -667,7 +666,7 @@
         filesCreated++;
         final String modes = sourceFile.statSync().modeString();
         if (modes != null && modes.contains('x')) {
-          os.makeExecutable(destinationFile);
+          globals.os.makeExecutable(destinationFile);
         }
       },
     );
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index ce53e93..fd2c618 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -125,7 +125,12 @@
           ),
       MacOSWorkflow: () => const MacOSWorkflow(),
       MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
-      OperatingSystemUtils: () => OperatingSystemUtils(),
+      OperatingSystemUtils: () => OperatingSystemUtils(
+        fileSystem: globals.fs,
+        logger: globals.logger,
+        platform: globals.platform,
+        processManager: globals.processManager,
+      ),
       PersistentToolState: () => PersistentToolState(),
       ProcessInfo: () => ProcessInfo(),
       ProcessUtils: () => ProcessUtils(
diff --git a/packages/flutter_tools/lib/src/desktop_device.dart b/packages/flutter_tools/lib/src/desktop_device.dart
index 65a2339..9250f5d 100644
--- a/packages/flutter_tools/lib/src/desktop_device.dart
+++ b/packages/flutter_tools/lib/src/desktop_device.dart
@@ -9,7 +9,6 @@
 import 'application_package.dart';
 import 'base/common.dart';
 import 'base/io.dart';
-import 'base/os.dart';
 import 'build_info.dart';
 import 'cache.dart';
 import 'convert.dart';
@@ -61,7 +60,7 @@
   DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
 
   @override
-  Future<String> get sdkNameAndVersion async => os.name;
+  Future<String> get sdkNameAndVersion async => globals.os.name;
 
   @override
   DeviceLogReader getLogReader({ ApplicationPackage app }) {
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index dbfe596..b50b770 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -12,7 +12,6 @@
 import 'base/context.dart';
 import 'base/file_system.dart';
 import 'base/logger.dart';
-import 'base/os.dart';
 import 'base/process.dart';
 import 'base/terminal.dart';
 import 'base/user_messages.dart';
@@ -636,9 +635,15 @@
       valid = ValidationType.partial;
     }
 
-    return ValidationResult(valid, messages,
+    return ValidationResult(
+      valid,
+      messages,
       statusInfo: userMessages.flutterStatusInfo(
-        versionChannel, frameworkVersion, os.name, globals.platform.localeName),
+        versionChannel,
+        frameworkVersion,
+        globals.os.name,
+        globals.platform.localeName,
+      ),
     );
   }
 }
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
index fbd40ca..937027f 100644
--- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
@@ -14,7 +14,6 @@
 import '../base/io.dart';
 import '../base/logger.dart';
 import '../base/net.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/time.dart';
 import '../build_info.dart';
@@ -257,7 +256,7 @@
       return LaunchResult.failed();
     }
     // Find out who the device thinks we are.
-    final int port = await os.findFreePort();
+    final int port = await globals.os.findFreePort();
     if (port == 0) {
       globals.printError('Failed to find a free port');
       return LaunchResult.failed();
@@ -733,7 +732,7 @@
 
   @override
   Future<int> forward(int devicePort, {int hostPort}) async {
-    hostPort ??= await os.findFreePort();
+    hostPort ??= await globals.os.findFreePort();
     if (hostPort == 0) {
       throwToolExit('Failed to forward port $devicePort. No free host-side ports');
     }
diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart
index 83fd491..ab7d62a 100644
--- a/packages/flutter_tools/lib/src/globals.dart
+++ b/packages/flutter_tools/lib/src/globals.dart
@@ -12,16 +12,18 @@
 import 'base/file_system.dart';
 import 'base/io.dart';
 import 'base/logger.dart';
+import 'base/os.dart';
 import 'base/terminal.dart';
 import 'cache.dart';
 import 'ios/mac.dart';
 import 'macos/xcode.dart';
 import 'version.dart';
 
-Logger get logger => context.get<Logger>();
+Artifacts get artifacts => context.get<Artifacts>();
 Cache get cache => context.get<Cache>();
 Config get config => context.get<Config>();
-Artifacts get artifacts => context.get<Artifacts>();
+Logger get logger => context.get<Logger>();
+OperatingSystemUtils get os => context.get<OperatingSystemUtils>();
 
 const FileSystem _kLocalFs = LocalFileSystem();
 
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 4119f63..40ddcd9 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -12,7 +12,6 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/utils.dart';
 import '../build_info.dart';
@@ -419,7 +418,7 @@
   if (globals.logger.hasTerminal) {
     tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_build_log_pipe.');
     scriptOutputPipeFile = tempDir.childFile('pipe_to_stdout');
-    os.makePipe(scriptOutputPipeFile.path);
+    globals.os.makePipe(scriptOutputPipeFile.path);
 
     Future<void> listenToScriptOutputLine() async {
       final List<String> lines = await scriptOutputPipeFile.readAsLines();
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 4f3873b..e37027f 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -14,7 +14,6 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/terminal.dart';
 import '../base/utils.dart';
@@ -118,7 +117,7 @@
     : project.ios.generatedEnvironmentVariableExportScript;
   generatedModuleBuildPhaseScript.createSync(recursive: true);
   generatedModuleBuildPhaseScript.writeAsStringSync(localsBuffer.toString());
-  os.chmod(generatedModuleBuildPhaseScript, '755');
+  globals.os.chmod(generatedModuleBuildPhaseScript, '755');
 }
 
 /// Build name parsed and validated from build info and manifest. Used for CFBundleShortVersionString.
diff --git a/packages/flutter_tools/lib/src/reporting/crash_reporting.dart b/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
index 9c54a9b..466ba63 100644
--- a/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
+++ b/packages/flutter_tools/lib/src/reporting/crash_reporting.dart
@@ -104,7 +104,7 @@
       req.fields['product'] = _kProductId;
       req.fields['version'] = flutterVersion;
       req.fields['osName'] = globals.platform.operatingSystem;
-      req.fields['osVersion'] = os.name; // this actually includes version
+      req.fields['osVersion'] = globals.os.name; // this actually includes version
       req.fields['type'] = _kDartTypeId;
       req.fields['error_runtime_type'] = '${error.runtimeType}';
       req.fields['error_message'] = '$error';
diff --git a/packages/flutter_tools/lib/src/reporting/reporting.dart b/packages/flutter_tools/lib/src/reporting/reporting.dart
index 9e0ba48..da24150 100644
--- a/packages/flutter_tools/lib/src/reporting/reporting.dart
+++ b/packages/flutter_tools/lib/src/reporting/reporting.dart
@@ -14,7 +14,6 @@
 import '../base/context.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
-import '../base/os.dart';
 import '../base/time.dart';
 import '../doctor.dart';
 import '../features.dart';
diff --git a/packages/flutter_tools/lib/src/reporting/usage.dart b/packages/flutter_tools/lib/src/reporting/usage.dart
index 79f9150..a6298fd 100644
--- a/packages/flutter_tools/lib/src/reporting/usage.dart
+++ b/packages/flutter_tools/lib/src/reporting/usage.dart
@@ -200,20 +200,28 @@
     assert(_analytics != null);
 
     // Report a more detailed OS version string than package:usage does by default.
-    _analytics.setSessionValue(cdKey(CustomDimensions.sessionHostOsDetails), os.name);
+    _analytics.setSessionValue(
+      cdKey(CustomDimensions.sessionHostOsDetails),
+      globals.os.name,
+    );
     // Send the branch name as the "channel".
-    _analytics.setSessionValue(cdKey(CustomDimensions.sessionChannelName),
-                               flutterVersion.getBranchName(redactUnknownBranches: true));
+    _analytics.setSessionValue(
+      cdKey(CustomDimensions.sessionChannelName),
+      flutterVersion.getBranchName(redactUnknownBranches: true),
+    );
     // For each flutter experimental feature, record a session value in a comma
     // separated list.
     final String enabledFeatures = allFeatures
-        .where((Feature feature) {
-          return feature.configSetting != null &&
-                 globals.config.getValue(feature.configSetting) == true;
-        })
-        .map((Feature feature) => feature.configSetting)
-        .join(',');
-    _analytics.setSessionValue(cdKey(CustomDimensions.enabledFlutterFeatures), enabledFeatures);
+      .where((Feature feature) {
+        return feature.configSetting != null &&
+               globals.config.getValue(feature.configSetting) == true;
+      })
+      .map((Feature feature) => feature.configSetting)
+      .join(',');
+    _analytics.setSessionValue(
+      cdKey(CustomDimensions.enabledFlutterFeatures),
+      enabledFeatures,
+    );
 
     // Record the host as the application installer ID - the context that flutter_tools is running in.
     if (globals.platform.environment.containsKey('FLUTTER_HOST')) {
diff --git a/packages/flutter_tools/lib/src/test/coverage_collector.dart b/packages/flutter_tools/lib/src/test/coverage_collector.dart
index 2d8e6a8..4f17576 100644
--- a/packages/flutter_tools/lib/src/test/coverage_collector.dart
+++ b/packages/flutter_tools/lib/src/test/coverage_collector.dart
@@ -9,7 +9,6 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
-import '../base/os.dart';
 import '../base/process.dart';
 import '../base/utils.dart';
 import '../dart/package_map.dart';
@@ -139,7 +138,7 @@
         return false;
       }
 
-      if (os.which('lcov') == null) {
+      if (globals.os.which('lcov') == null) {
         String installMessage = 'Please install lcov.';
         if (globals.platform.isLinux) {
           installMessage = 'Consider running "sudo apt-get install lcov".';
diff --git a/packages/flutter_tools/lib/src/web/chrome.dart b/packages/flutter_tools/lib/src/web/chrome.dart
index e03b9aa..99953cf 100644
--- a/packages/flutter_tools/lib/src/web/chrome.dart
+++ b/packages/flutter_tools/lib/src/web/chrome.dart
@@ -11,7 +11,6 @@
 import '../base/context.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
-import '../base/os.dart';
 import '../convert.dart';
 import '../globals.dart' as globals;
 
@@ -118,7 +117,7 @@
       }
     }
 
-    final int port = await os.findFreePort();
+    final int port = await globals.os.findFreePort();
     final List<String> args = <String>[
       chromeExecutable,
       // Using a tmp directory ensures that a new instance of chrome launches