Migrate flutter_tools to use package:platform (#7642)

diff --git a/packages/flutter_tools/bin/fuchsia_builder.dart b/packages/flutter_tools/bin/fuchsia_builder.dart
index 5272662..40df530 100644
--- a/packages/flutter_tools/bin/fuchsia_builder.dart
+++ b/packages/flutter_tools/bin/fuchsia_builder.dart
@@ -14,6 +14,7 @@
 import '../lib/src/base/io.dart';
 import '../lib/src/base/logger.dart';
 import '../lib/src/base/os.dart';
+import '../lib/src/base/platform.dart';
 import '../lib/src/cache.dart';
 import '../lib/src/flx.dart';
 import '../lib/src/globals.dart';
@@ -38,6 +39,7 @@
   executableContext.setVariable(Logger, new StdoutLogger());
   executableContext.runInZone(() {
     // Initialize the context with some defaults.
+    context.putIfAbsent(Platform, () => new LocalPlatform());
     context.putIfAbsent(FileSystem, () => new LocalFileSystem());
     context.putIfAbsent(ProcessManager, () => new LocalProcessManager());
     context.putIfAbsent(Logger, () => new StdoutLogger());
@@ -63,7 +65,7 @@
     printError('Missing option! All options must be specified.');
     exit(1);
   }
-  Cache.flutterRoot = Platform.environment['FLUTTER_ROOT'];
+  Cache.flutterRoot = platform.environment['FLUTTER_ROOT'];
   String outputPath = argResults[_kOptionOutput];
   try {
     await assemble(
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart
index 7eeb911..00eb8c8 100644
--- a/packages/flutter_tools/lib/executable.dart
+++ b/packages/flutter_tools/lib/executable.dart
@@ -15,6 +15,7 @@
 import 'src/base/io.dart';
 import 'src/base/logger.dart';
 import 'src/base/os.dart';
+import 'src/base/platform.dart';
 import 'src/base/process.dart';
 import 'src/base/utils.dart';
 import 'src/cache.dart';
@@ -100,6 +101,7 @@
     // in those locations as well to see if you need a similar update there.
 
     // Seed these context entries first since others depend on them
+    context.putIfAbsent(Platform, () => new LocalPlatform());
     context.putIfAbsent(FileSystem, () => new LocalFileSystem());
     context.putIfAbsent(ProcessManager, () => new LocalProcessManager());
     context.putIfAbsent(Logger, () => new StdoutLogger());
diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index e1cce35..dec3630 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -8,8 +8,8 @@
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
-import '../base/io.dart';
 import '../base/os.dart';
+import '../base/platform.dart';
 import '../globals.dart';
 
 AndroidSdk get androidSdk => context[AndroidSdk];
@@ -64,15 +64,15 @@
 
   static AndroidSdk locateAndroidSdk() {
     String androidHomeDir;
-    if (Platform.environment.containsKey(kAndroidHome)) {
-      androidHomeDir = Platform.environment[kAndroidHome];
-    } else if (Platform.isLinux) {
+    if (platform.environment.containsKey(kAndroidHome)) {
+      androidHomeDir = platform.environment[kAndroidHome];
+    } else if (platform.isLinux) {
       if (homeDirPath != null)
         androidHomeDir = path.join(homeDirPath, 'Android', 'Sdk');
-    } else if (Platform.isMacOS) {
+    } else if (platform.isMacOS) {
       if (homeDirPath != null)
         androidHomeDir = path.join(homeDirPath, 'Library', 'Android', 'sdk');
-    } else if (Platform.isWindows) {
+    } else if (platform.isWindows) {
       if (homeDirPath != null)
         androidHomeDir = path.join(homeDirPath, 'AppData', 'Local', 'Android', 'sdk');
     }
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 370fe91..2ad9b4d 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -6,6 +6,7 @@
 
 import '../base/io.dart';
 import '../base/os.dart';
+import '../base/platform.dart';
 import '../base/process_manager.dart';
 import '../doctor.dart';
 import '../globals.dart';
@@ -30,8 +31,8 @@
     String sdkVersionText;
 
     if (androidSdk == null) {
-      if (Platform.environment.containsKey(kAndroidHome)) {
-        String androidHomeDir = Platform.environment[kAndroidHome];
+      if (platform.environment.containsKey(kAndroidHome)) {
+        String androidHomeDir = platform.environment[kAndroidHome];
         messages.add(new ValidationMessage.error(
           '$kAndroidHome = $androidHomeDir\n'
           'but Android Studio / Android SDK not found at this location.'
@@ -56,8 +57,8 @@
         ));
       }
 
-      if (Platform.environment.containsKey(kAndroidHome)) {
-        String androidHomeDir = Platform.environment[kAndroidHome];
+      if (platform.environment.containsKey(kAndroidHome)) {
+        String androidHomeDir = platform.environment[kAndroidHome];
         messages.add(new ValidationMessage('$kAndroidHome = $androidHomeDir'));
       }
 
diff --git a/packages/flutter_tools/lib/src/base/common.dart b/packages/flutter_tools/lib/src/base/common.dart
index 32ca620..9ddc62e 100644
--- a/packages/flutter_tools/lib/src/base/common.dart
+++ b/packages/flutter_tools/lib/src/base/common.dart
@@ -4,7 +4,7 @@
 
 import 'package:path/path.dart' as path;
 
-import 'io.dart';
+import 'platform.dart';
 
 const int kDefaultObservatoryPort = 8100;
 const int kDefaultDiagnosticPort  = 8101;
@@ -13,9 +13,9 @@
 /// Return the absolute path of the user's home directory
 String get homeDirPath {
   if (_homeDirPath == null) {
-    _homeDirPath = Platform.isWindows
-        ? Platform.environment['USERPROFILE']
-        : Platform.environment['HOME'];
+    _homeDirPath = platform.isWindows
+        ? platform.environment['USERPROFILE']
+        : platform.environment['HOME'];
     if (_homeDirPath != null)
       _homeDirPath = path.absolute(_homeDirPath);
   }
diff --git a/packages/flutter_tools/lib/src/base/config.dart b/packages/flutter_tools/lib/src/base/config.dart
index dc10ae2..fb975a1 100644
--- a/packages/flutter_tools/lib/src/base/config.dart
+++ b/packages/flutter_tools/lib/src/base/config.dart
@@ -8,7 +8,7 @@
 
 import 'context.dart';
 import 'file_system.dart';
-import 'io.dart';
+import 'platform.dart';
 
 class Config {
   Config([File configFile]) {
@@ -46,7 +46,7 @@
 }
 
 String _userHomeDir() {
-  String envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
-  String value = Platform.environment[envKey];
+  String envKey = platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
+  String value = platform.environment[envKey];
   return value == null ? '.' : value;
 }
diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart
index 9b2d717..d044c68 100644
--- a/packages/flutter_tools/lib/src/base/io.dart
+++ b/packages/flutter_tools/lib/src/base/io.dart
@@ -11,16 +11,20 @@
 /// access with mockable (or in-memory) file systems, making our tests hermetic
 /// vis-a-vis file system access.
 ///
-/// To ensure that all file system access within Flutter tools goes through the
-/// proper APIs, we forbid direct imports of `dart:io` (via a test), forcing
-/// all callers to instead import this file, which exports the blessed subset
-/// of `dart:io` that is legal to use in Flutter tools.
+/// We also use `package:platform` to provide an abstraction away from the
+/// static methods in the `dart:io` `Platform` class (see `platform.dart`). As
+/// such, do not export Platform from this file!
 ///
-/// Because of the nature of this file, it is important that **no file APIs
-/// be exported from `dart:io` in this file**! Moreover, be careful about any
-/// additional exports that you add to this file, as doing so will increase the
-/// API surface that we have to test in Flutter tools, and the APIs in `dart:io`
-/// can sometimes be hard to use in tests.
+/// To ensure that all file system and platform API access within Flutter tools
+/// goes through the proper APIs, we forbid direct imports of `dart:io` (via a
+/// test), forcing all callers to instead import this file, which exports the
+/// blessed subset of `dart:io` that is legal to use in Flutter tools.
+///
+/// Because of the nature of this file, it is important that **platform and file
+/// APIs not be exported from `dart:io` in this file**! Moreover, be careful
+/// about any additional exports that you add to this file, as doing so will
+/// increase the API surface that we have to test in Flutter tools, and the APIs
+/// in `dart:io` can sometimes be hard to use in tests.
 import 'dart:io' as io show exit, exitCode;
 
 import 'package:meta/meta.dart';
@@ -28,7 +32,10 @@
 export 'dart:io'
     show
         BytesBuilder,
+        // Directory         NO! Use `file_system.dart`
         exitCode,
+        // File              NO! Use `file_system.dart`
+        // FileSystemEntity  NO! Use `file_system.dart`
         GZIP,
         InternetAddress,
         IOException,
@@ -40,13 +47,15 @@
         HttpRequest,
         HttpServer,
         HttpStatus,
+        // Link              NO! Use `file_system.dart`
         pid,
-        Platform,
+        // Platform          NO! use `platform.dart`
         Process,
         ProcessException,
         ProcessResult,
         ProcessSignal,
         ProcessStartMode,
+        // RandomAccessFile  NO! Use `file_system.dart`
         ServerSocket,
         stderr,
         stdin,
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart
index 61ebbac..14bfbde 100644
--- a/packages/flutter_tools/lib/src/base/logger.dart
+++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -8,6 +8,7 @@
 import 'package:stack_trace/stack_trace.dart';
 
 import 'io.dart';
+import 'platform.dart';
 
 final AnsiTerminal terminal = new AnsiTerminal();
 
@@ -202,7 +203,7 @@
 class AnsiTerminal {
   AnsiTerminal() {
     // TODO(devoncarew): This detection does not work for Windows.
-    String term = Platform.environment['TERM'];
+    String term = platform.environment['TERM'];
     supportsColor = term != null && term != 'dumb';
   }
 
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart
index 1236811..011a7c4 100644
--- a/packages/flutter_tools/lib/src/base/os.dart
+++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -10,6 +10,7 @@
 import 'context.dart';
 import 'file_system.dart';
 import 'io.dart';
+import 'platform.dart';
 import 'process.dart';
 import 'process_manager.dart';
 
@@ -18,7 +19,7 @@
 
 abstract class OperatingSystemUtils {
   factory OperatingSystemUtils() {
-    if (Platform.isWindows) {
+    if (platform.isWindows) {
       return new _WindowsUtils();
     } else {
       return new _PosixUtils();
@@ -27,8 +28,9 @@
 
   OperatingSystemUtils._private();
 
-  String get operatingSystem => Platform.operatingSystem;
 
+  // TODO(tvolkert): Remove these and migrate callers to Platform
+  String get operatingSystem => platform.operatingSystem;
   bool get isMacOS => operatingSystem == 'macos';
   bool get isWindows => operatingSystem == 'windows';
   bool get isLinux => operatingSystem == 'linux';
@@ -46,7 +48,7 @@
   void unzip(File file, Directory targetDirectory);
 
   /// Returns the name of the [binaryName] executable.
-  /// 
+  ///
   /// No-op on most OS.
   /// On Windows it returns [binaryName].[winExtension], if [winExtension] is
   /// specified, or [binaryName].exe otherwise.
diff --git a/packages/flutter_tools/lib/src/base/platform.dart b/packages/flutter_tools/lib/src/base/platform.dart
new file mode 100644
index 0000000..6de07dd
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/platform.dart
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:platform/platform.dart';
+
+import 'context.dart';
+
+export 'package:platform/platform.dart';
+
+const Platform _kLocalPlatform = const LocalPlatform();
+
+Platform get platform => context == null ? _kLocalPlatform : context[Platform];
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index 1cdd05a..67518f3 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -10,15 +10,15 @@
 import 'package:path/path.dart' as path;
 
 import 'file_system.dart';
-import 'io.dart';
+import 'platform.dart';
 
 bool get isRunningOnBot {
   // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
   // CHROME_HEADLESS is one property set on Flutter's Chrome Infra bots.
   return
-    Platform.environment['TRAVIS'] == 'true' ||
-    Platform.environment['CONTINUOUS_INTEGRATION'] == 'true' ||
-    Platform.environment['CHROME_HEADLESS'] == '1';
+    platform.environment['TRAVIS'] == 'true' ||
+    platform.environment['CONTINUOUS_INTEGRATION'] == 'true' ||
+    platform.environment['CHROME_HEADLESS'] == '1';
 }
 
 String hex(List<int> bytes) {
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index e4305e3..07b979d 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -5,7 +5,7 @@
 import 'package:path/path.dart' as path;
 
 import 'base/context.dart';
-import 'base/io.dart';
+import 'base/platform.dart';
 import 'base/utils.dart';
 import 'globals.dart';
 
@@ -106,9 +106,9 @@
 }
 
 HostPlatform getCurrentHostPlatform() {
-  if (Platform.isMacOS)
+  if (platform.isMacOS)
     return HostPlatform.darwin_x64;
-  if (Platform.isLinux)
+  if (platform.isLinux)
     return HostPlatform.linux_x64;
 
   printError('Unsupported host platform, defaulting to Linux');
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index b5dac2d..c2db5a6 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -10,10 +10,10 @@
 
 import 'base/context.dart';
 import 'base/file_system.dart';
-import 'base/io.dart';
 import 'base/logger.dart';
 import 'base/net.dart';
 import 'base/os.dart';
+import 'base/platform.dart';
 import 'globals.dart';
 
 /// A wrapper around the `bin/cache/` directory.
@@ -84,7 +84,7 @@
 
   static String get dartSdkVersion {
     if (_dartSdkVersion == null) {
-      _dartSdkVersion = Platform.version;
+      _dartSdkVersion = platform.version;
     }
     return _dartSdkVersion;
   }
@@ -265,9 +265,9 @@
 
     if (cache.includeAllPlatforms)
       dirs.addAll(<String>['ios', 'ios-profile', 'ios-release', 'linux-x64']);
-    else if (Platform.isMacOS)
+    else if (platform.isMacOS)
       dirs.addAll(<String>['ios', 'ios-profile', 'ios-release']);
-    else if (Platform.isLinux)
+    else if (platform.isLinux)
       dirs.add('linux-x64');
 
     return dirs;
@@ -279,9 +279,9 @@
       return <List<String>>[]
         ..addAll(_osxToolsDirs)
         ..addAll(_linuxToolsDirs);
-    else if (Platform.isMacOS)
+    else if (platform.isMacOS)
       return _osxToolsDirs;
-    else if (Platform.isLinux)
+    else if (platform.isLinux)
       return _linuxToolsDirs;
     else
       return <List<String>>[];
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 8986109..9b3c90a 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -11,6 +11,7 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
+import '../base/platform.dart';
 import '../base/process_manager.dart';
 import '../base/os.dart';
 import '../cache.dart';
@@ -190,7 +191,7 @@
     }
     testArgs.addAll(files);
 
-    final String shellPath = tools.getHostToolPath(HostTool.SkyShell) ?? Platform.environment['SKY_SHELL'];
+    final String shellPath = tools.getHostToolPath(HostTool.SkyShell) ?? platform.environment['SKY_SHELL'];
     if (!fs.isFileSync(shellPath))
       throwToolExit('Cannot find Flutter shell at $shellPath');
     loader.installHook(shellPath: shellPath, collector: collector, debuggerMode: argResults['start-paused']);
diff --git a/packages/flutter_tools/lib/src/dart/sdk.dart b/packages/flutter_tools/lib/src/dart/sdk.dart
index 92f93de..150c260 100644
--- a/packages/flutter_tools/lib/src/dart/sdk.dart
+++ b/packages/flutter_tools/lib/src/dart/sdk.dart
@@ -4,7 +4,7 @@
 
 import 'package:path/path.dart' as path;
 
-import '../base/io.dart';
+import '../base/platform.dart';
 import '../cache.dart';
 
 /// Locate the Dart SDK.
@@ -16,5 +16,5 @@
 /// ==> `pub.bat`.  The default SDK location can be overridden with a specified
 /// [sdkLocation].
 String sdkBinaryName(String name, { String sdkLocation }) {
-  return path.absolute(path.join(sdkLocation ?? dartSdkPath, 'bin', Platform.isWindows ? '$name.bat' : name));
+  return path.absolute(path.join(sdkLocation ?? dartSdkPath, 'bin', platform.isWindows ? '$name.bat' : name));
 }
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 8593fe4..10ea568 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -163,6 +163,8 @@
   // supported by Flutter, and, if not, why.
   String supportMessage() => isSupported() ? "Supported" : "Unsupported";
 
+  // TODO(tvolkert): Rename to `targetPlatform`, and remove the "as p"
+  // aliases on the `platform.dart` imports where applicable.
   TargetPlatform get platform;
 
   String get sdkNameAndVersion;
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index cb982f9..5ebe78d 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -3,16 +3,16 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert' show UTF8;
 
 import 'package:archive/archive.dart';
-import 'dart:convert' show UTF8;
 import 'package:path/path.dart' as path;
 
 import 'android/android_workflow.dart';
 import 'base/common.dart';
 import 'base/context.dart';
 import 'base/file_system.dart';
-import 'base/io.dart';
+import 'base/platform.dart';
 import 'device.dart';
 import 'globals.dart';
 import 'ios/ios_workflow.dart';
@@ -27,7 +27,7 @@
 };
 
 String osName() {
-  String os = Platform.operatingSystem;
+  String os = platform.operatingSystem;
   return _osNames.containsKey(os) ? _osNames[os] : os;
 }
 
@@ -182,7 +182,7 @@
     if (type == ValidationType.missing)
       return '[x]';
     else if (type == ValidationType.installed)
-      return Platform.isWindows ? '[√]' : '[✓]';
+      return platform.isWindows ? '[√]' : '[✓]';
     else
       return '[-]';
   }
@@ -217,7 +217,7 @@
     messages.add(new ValidationMessage('Engine revision ${version.engineRevisionShort}'));
     messages.add(new ValidationMessage('Tools Dart version ${version.dartSdkVersion}'));
 
-    if (Platform.isWindows) {
+    if (platform.isWindows) {
       valid = ValidationType.missing;
 
       messages.add(new ValidationMessage.error(
@@ -254,9 +254,9 @@
   };
 
   static Iterable<DoctorValidator> get installedValidators {
-    if (Platform.isLinux || Platform.isWindows)
+    if (platform.isLinux || platform.isWindows)
       return IntelliJValidatorOnLinuxAndWindows.installed;
-    if (Platform.isMacOS)
+    if (platform.isMacOS)
       return IntelliJValidatorOnMac.installed;
     return <DoctorValidator>[];
   }
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index 424c495..bd3dde8 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -9,6 +9,7 @@
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/os.dart';
+import '../base/platform.dart' as p;
 import '../base/process.dart';
 import '../base/process_manager.dart';
 import '../build_info.dart';
@@ -28,7 +29,7 @@
   IOSDevices() : super('IOSDevices');
 
   @override
-  bool get supportsPlatform => Platform.isMacOS;
+  bool get supportsPlatform => p.platform.isMacOS;
 
   @override
   List<Device> pollingGetDevices() => IOSDevice.getAttachedDevices();
@@ -125,7 +126,7 @@
       try {
         command = runCheckedSync(<String>['which', command]).trim();
       } catch (e) {
-        if (Platform.isMacOS) {
+        if (p.platform.isMacOS) {
           printError('$command not found. $macInstructions');
         } else {
           printError('Cannot control iOS devices or simulators. $command is not available on your platform.');
@@ -314,7 +315,7 @@
   }
 
   Future<bool> pushFile(ApplicationPackage app, String localFile, String targetFile) async {
-    if (Platform.isMacOS) {
+    if (p.platform.isMacOS) {
       runSync(<String>[
         pusherPath,
         '-t',
diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
index cc89764..f338816 100644
--- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart
+++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
@@ -6,6 +6,7 @@
 
 import '../base/io.dart';
 import '../base/os.dart';
+import '../base/platform.dart';
 import '../base/process.dart';
 import '../doctor.dart';
 import 'mac.dart';
@@ -16,7 +17,7 @@
   IOSWorkflow() : super('iOS toolchain - develop for iOS devices');
 
   @override
-  bool get appliesToHostPlatform => Platform.isMacOS;
+  bool get appliesToHostPlatform => platform.isMacOS;
 
   // We need xcode (+simctl) to list simulator devices, and idevice_id to list real devices.
   @override
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 0a451ce..13114c0 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -11,6 +11,7 @@
 import '../base/context.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
+import '../base/platform.dart';
 import '../base/process.dart';
 import '../base/process_manager.dart';
 import '../build_info.dart';
@@ -220,7 +221,7 @@
 final String _xcodeRequirement = 'Xcode 7.0 or greater is required to develop for iOS.';
 
 bool _checkXcodeVersion() {
-  if (!Platform.isMacOS)
+  if (!platform.isMacOS)
     return false;
   try {
     String version = runCheckedSync(<String>['xcodebuild', '-version']);
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index 4a50fd6..b9e491c 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -13,6 +13,7 @@
 import '../base/context.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
+import '../base/platform.dart' as p;
 import '../base/process.dart';
 import '../base/process_manager.dart';
 import '../build_info.dart';
@@ -31,7 +32,7 @@
   IOSSimulators() : super('IOSSimulators');
 
   @override
-  bool get supportsPlatform => Platform.isMacOS;
+  bool get supportsPlatform => p.platform.isMacOS;
 
   @override
   List<Device> pollingGetDevices() => IOSSimulatorUtils.instance.getAttachedDevices();
@@ -359,7 +360,7 @@
 
   @override
   bool isSupported() {
-    if (!Platform.isMacOS) {
+    if (!p.platform.isMacOS) {
       _supportMessage = "Not supported on a non Mac host";
       return false;
     }
@@ -532,7 +533,7 @@
 
   Future<bool> pushFile(
       ApplicationPackage app, String localFile, String targetFile) async {
-    if (Platform.isMacOS) {
+    if (p.platform.isMacOS) {
       String simulatorHomeDirectory = _getSimulatorAppHomeDirectory(app);
       runCheckedSync(<String>['cp', localFile, path.join(simulatorHomeDirectory, targetFile)]);
       return true;
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 84158d2..2ec6d89 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -12,8 +12,8 @@
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
-import '../base/io.dart';
 import '../base/logger.dart';
+import '../base/platform.dart';
 import '../base/process.dart';
 import '../base/process_manager.dart';
 import '../cache.dart';
@@ -117,12 +117,12 @@
   }
 
   static String get _defaultFlutterRoot {
-    if (Platform.environment.containsKey(kFlutterRootEnvironmentVariableName))
-      return Platform.environment[kFlutterRootEnvironmentVariableName];
+    if (platform.environment.containsKey(kFlutterRootEnvironmentVariableName))
+      return platform.environment[kFlutterRootEnvironmentVariableName];
     try {
-      if (Platform.script.scheme == 'data')
+      if (platform.script.scheme == 'data')
         return '../..'; // we're running as a test
-      String script = Platform.script.toFilePath();
+      String script = platform.script.toFilePath();
       if (path.basename(script) == kSnapshotFileName)
         return path.dirname(path.dirname(path.dirname(script)));
       if (path.basename(script) == kFlutterToolsScriptFileName)
@@ -179,7 +179,7 @@
     // enginePath's initialiser uses it).
     Cache.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root']));
 
-    if (Platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true')
+    if (platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true')
       await Cache.lock();
 
     if (globalResults['suppress-analytics'])
@@ -219,7 +219,7 @@
   }
 
   String _findEnginePath(ArgResults globalResults) {
-    String engineSourcePath = globalResults['local-engine-src-path'] ?? Platform.environment[kFlutterEngineEnvironmentVariableName];
+    String engineSourcePath = globalResults['local-engine-src-path'] ?? platform.environment[kFlutterEngineEnvironmentVariableName];
 
     if (engineSourcePath == null && globalResults['local-engine'] != null) {
       try {
diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml
index 487d36d..2ff42c8 100644
--- a/packages/flutter_tools/pubspec.yaml
+++ b/packages/flutter_tools/pubspec.yaml
@@ -22,6 +22,7 @@
   mustache: ^0.2.5
   package_config: '>=0.1.5 <2.0.0'
   path: ^1.4.0
+  platform: 1.0.1
   process: 1.0.1
   pub_semver: ^1.0.0
   stack_trace: ^1.4.0
diff --git a/packages/flutter_tools/test/daemon_test.dart b/packages/flutter_tools/test/daemon_test.dart
index c269d9f..28a7ff8 100644
--- a/packages/flutter_tools/test/daemon_test.dart
+++ b/packages/flutter_tools/test/daemon_test.dart
@@ -5,8 +5,8 @@
 import 'dart:async';
 
 import 'package:flutter_tools/src/base/context.dart';
-import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/commands/daemon.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/doctor.dart';
@@ -32,9 +32,10 @@
     setUp(() {
       appContext = new AppContext();
       notifyingLogger = new NotifyingLogger();
+      appContext.setVariable(Platform, new LocalPlatform());
       appContext.setVariable(Logger, notifyingLogger);
       appContext.setVariable(Doctor, new Doctor());
-      if (Platform.isMacOS)
+      if (platform.isMacOS)
         appContext.setVariable(XCode, new XCode());
       appContext.setVariable(DeviceManager, new MockDeviceManager());
     });
diff --git a/packages/flutter_tools/test/dart_dependencies_test.dart b/packages/flutter_tools/test/dart_dependencies_test.dart
index bf0a852..120ca25 100644
--- a/packages/flutter_tools/test/dart_dependencies_test.dart
+++ b/packages/flutter_tools/test/dart_dependencies_test.dart
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/dart/dependencies.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'src/context.dart';
 
 void main()  {
   group('DartDependencySetBuilder', () {
-    final String basePath = path.dirname(Platform.script.path);
+    final String basePath = path.dirname(platform.script.path);
     final String dataPath = path.join(basePath, 'data', 'dart_dependencies_test');
     testUsingContext('good', () {
       final String testPath = path.join(dataPath, 'good');
diff --git a/packages/flutter_tools/test/dependency_checker_test.dart b/packages/flutter_tools/test/dependency_checker_test.dart
index b3b3992..89d480e 100644
--- a/packages/flutter_tools/test/dependency_checker_test.dart
+++ b/packages/flutter_tools/test/dependency_checker_test.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/io.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/dart/dependencies.dart';
 import 'package:flutter_tools/src/dependency_checker.dart';
 import 'package:path/path.dart' as path;
@@ -12,7 +12,7 @@
 
 void main()  {
   group('DependencyChecker', () {
-    final String basePath = path.dirname(Platform.script.path);
+    final String basePath = path.dirname(platform.script.path);
     final String dataPath = path.join(basePath, 'data', 'dart_dependencies_test');
     testUsingContext('good', () {
       final String testPath = path.join(dataPath, 'good');
diff --git a/packages/flutter_tools/test/forbid_dart_io_test.dart b/packages/flutter_tools/test/forbid_dart_io_test.dart
index c361787..323055d 100644
--- a/packages/flutter_tools/test/forbid_dart_io_test.dart
+++ b/packages/flutter_tools/test/forbid_dart_io_test.dart
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/base/io.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:test/test.dart';
 
 void main() {
   setUp(() {
-    String flutterRoot = Platform.environment['FLUTTER_ROOT'];
+    String flutterRoot = platform.environment['FLUTTER_ROOT'];
     assert(fs.currentDirectory.path == '$flutterRoot/packages/flutter_tools');
   });
 
diff --git a/packages/flutter_tools/test/os_utils_test.dart b/packages/flutter_tools/test/os_utils_test.dart
index d165b6a..5d87be1 100644
--- a/packages/flutter_tools/test/os_utils_test.dart
+++ b/packages/flutter_tools/test/os_utils_test.dart
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
@@ -28,7 +28,7 @@
       os.makeExecutable(file);
 
       // Skip this test on windows.
-      if (!Platform.isWindows) {
+      if (!platform.isWindows) {
         String mode = file.statSync().modeString();
         // rwxr--r--
         expect(mode.substring(0, 3), endsWith('x'));
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index b9db65f..04d3df6 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -7,9 +7,9 @@
 import 'package:flutter_tools/src/base/config.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
-import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/devfs.dart';
@@ -42,6 +42,7 @@
 
     // Initialize the test context with some default mocks.
     // Seed these context entries first since others depend on them
+    testContext.putIfAbsent(Platform, () => new LocalPlatform());
     testContext.putIfAbsent(FileSystem, () => new LocalFileSystem());
     testContext.putIfAbsent(ProcessManager, () => new LocalProcessManager());
     testContext.putIfAbsent(Logger, () => new BufferLogger());
@@ -68,7 +69,7 @@
     testContext.putIfAbsent(SimControl, () => new MockSimControl());
     testContext.putIfAbsent(Usage, () => new MockUsage());
 
-    final String basePath = path.dirname(Platform.script.path);
+    final String basePath = path.dirname(platform.script.path);
     final String flutterRoot =
         path.normalize(path.join(basePath, '..', '..', '..'));
     try {
@@ -148,7 +149,7 @@
   //     That way it wouldn't really matter what the mock returns here.
   @override
   String getExecutableName(String binaryName, { String winExtension }) {
-    if (!Platform.isWindows)
+    if (!platform.isWindows)
       return binaryName;
     winExtension ??= 'exe';
     if (path.extension(binaryName).isEmpty && winExtension.isNotEmpty)