introduce globals scoped to the app's context
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart
index e92e058..b6ff950 100644
--- a/packages/flutter_tools/lib/executable.dart
+++ b/packages/flutter_tools/lib/executable.dart
@@ -8,6 +8,8 @@
 import 'package:args/command_runner.dart';
 import 'package:stack_trace/stack_trace.dart';
 
+import 'src/base/context.dart';
+import 'src/base/logger.dart';
 import 'src/base/process.dart';
 import 'src/commands/analyze.dart';
 import 'src/commands/apk.dart';
@@ -27,6 +29,7 @@
 import 'src/commands/test.dart';
 import 'src/commands/trace.dart';
 import 'src/commands/upgrade.dart';
+import 'src/device.dart';
 import 'src/runner/flutter_command_runner.dart';
 
 /// Main entry point for commands.
@@ -62,7 +65,12 @@
     if (args.isNotEmpty && args[0] == 'init')
       args[0] = 'create';
 
+    // Initialize globals.
+    context[Logger] = new StdoutLogger();
+    context[DeviceManager] = new DeviceManager();
+
     dynamic result = await runner.run(args);
+
     if (result is int)
       exit(result);
   }, onError: (error, Chain chain) {
diff --git a/packages/flutter_tools/lib/src/android/adb.dart b/packages/flutter_tools/lib/src/android/adb.dart
index aad03e3..e8b0f94 100644
--- a/packages/flutter_tools/lib/src/android/adb.dart
+++ b/packages/flutter_tools/lib/src/android/adb.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'dart:io';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 
 // https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
diff --git a/packages/flutter_tools/lib/src/android/device_android.dart b/packages/flutter_tools/lib/src/android/device_android.dart
index e0eadf9..c55e0d4 100644
--- a/packages/flutter_tools/lib/src/android/device_android.dart
+++ b/packages/flutter_tools/lib/src/android/device_android.dart
@@ -10,7 +10,7 @@
 
 import '../application_package.dart';
 import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/os.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
index 123b752..4d304ed 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -8,7 +8,7 @@
 import 'package:archive/archive.dart';
 import 'package:path/path.dart' as path;
 
-import 'base/context.dart';
+import 'base/globals.dart';
 import 'base/os.dart';
 import 'base/process.dart';
 import 'build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/base/context.dart b/packages/flutter_tools/lib/src/base/context.dart
index 21054a4..8c1f54d 100644
--- a/packages/flutter_tools/lib/src/base/context.dart
+++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -3,9 +3,8 @@
 // found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 
-final AppContext _defaultContext = new _DefaultAppContext();
+final AppContext _defaultContext = new AppContext();
 
 /// A singleton for application functionality. This singleton can be different
 /// on a per-Zone basis.
@@ -14,57 +13,42 @@
   return currentContext == null ? _defaultContext : currentContext;
 }
 
-/// Display an error level message to the user. Commands should use this if they
-/// fail in some way.
-void printError(String message, [StackTrace stackTrace]) => context.printError(message, stackTrace);
+class AppContext {
+  Map<Type, dynamic> _instances = <Type, dynamic>{};
 
-/// Display normal output of the command. This should be used for things like
-/// progress messages, success messages, or just normal command output.
-void printStatus(String message) => context.printStatus(message);
+  dynamic getVariable(Type type) {
+    if (_instances.containsKey(type))
+      return _instances[type];
 
-/// Use this for verbose tracing output. Users can turn this output on in order
-/// to help diagnose issues with the toolchain or with their setup.
-void printTrace(String message) => context.printTrace(message);
-
-abstract class AppContext {
-  bool get verbose;
-  set verbose(bool value);
-
-  void printError(String message, [StackTrace stackTrace]);
-  void printStatus(String message);
-  void printTrace(String message);
-}
-
-class _DefaultAppContext implements AppContext {
-  DateTime _startTime = new DateTime.now();
-
-  bool _verbose = false;
-
-  bool get verbose => _verbose;
-
-  set verbose(bool value) {
-    _verbose = value;
+    AppContext parent = _calcParent(Zone.current);
+    return parent?.getVariable(type);
   }
 
-  void printError(String message, [StackTrace stackTrace]) {
-    stderr.writeln(_prefix + message);
-    if (stackTrace != null)
-      stderr.writeln(stackTrace);
+  void setVariable(Type type, dynamic instance) {
+    _instances[type] = instance;
   }
 
-  void printStatus(String message) {
-    print(_prefix + message);
+  dynamic operator[](Type type) => getVariable(type);
+
+  void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
+
+  AppContext _calcParent(Zone zone) {
+    if (this == _defaultContext)
+      return null;
+
+    Zone parentZone = zone.parent;
+    if (parentZone == null)
+      return _defaultContext;
+
+    AppContext deps = parentZone['context'];
+    if (deps == this) {
+      return _calcParent(parentZone);
+    } else {
+      return deps != null ? deps : _defaultContext;
+    }
   }
 
-  void printTrace(String message) {
-    if (_verbose)
-      print('$_prefix- $message');
-  }
-
-  String get _prefix {
-    if (!_verbose)
-      return '';
-    Duration elapsed = new DateTime.now().difference(_startTime);
-    return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
+  dynamic runInZone(dynamic method()) {
+    return runZoned(method, zoneValues: {'context': this});
   }
 }
diff --git a/packages/flutter_tools/lib/src/base/globals.dart b/packages/flutter_tools/lib/src/base/globals.dart
new file mode 100644
index 0000000..5c86fb2
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/globals.dart
@@ -0,0 +1,22 @@
+// 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 '../device.dart';
+import 'context.dart';
+import 'logger.dart';
+
+DeviceManager get deviceManager => context[DeviceManager];
+Logger get logger => context[Logger];
+
+/// Display an error level message to the user. Commands should use this if they
+/// fail in some way.
+void printError(String message, [StackTrace stackTrace]) => logger.printError(message, stackTrace);
+
+/// Display normal output of the command. This should be used for things like
+/// progress messages, success messages, or just normal command output.
+void printStatus(String message) => logger.printStatus(message);
+
+/// Use this for verbose tracing output. Users can turn this output on in order
+/// to help diagnose issues with the toolchain or with their setup.
+void printTrace(String message) => logger.printTrace(message);
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart
new file mode 100644
index 0000000..0489279
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -0,0 +1,65 @@
+// 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 'dart:io';
+
+abstract class Logger {
+  bool verbose = false;
+
+  /// Display an error level message to the user. Commands should use this if they
+  /// fail in some way.
+  void printError(String message, [StackTrace stackTrace]);
+
+  /// Display normal output of the command. This should be used for things like
+  /// progress messages, success messages, or just normal command output.
+  void printStatus(String message);
+
+  /// Use this for verbose tracing output. Users can turn this output on in order
+  /// to help diagnose issues with the toolchain or with their setup.
+  void printTrace(String message);
+}
+
+class StdoutLogger implements Logger {
+  DateTime _startTime = new DateTime.now();
+
+  bool verbose = false;
+
+  void printError(String message, [StackTrace stackTrace]) {
+    stderr.writeln(_prefix + message);
+    if (stackTrace != null)
+      stderr.writeln(stackTrace);
+  }
+
+  void printStatus(String message) {
+    print(_prefix + message);
+  }
+
+  void printTrace(String message) {
+    if (verbose)
+      print('$_prefix- $message');
+  }
+
+  String get _prefix {
+    if (!verbose)
+      return '';
+    Duration elapsed = new DateTime.now().difference(_startTime);
+    return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
+  }
+}
+
+class BufferLogger implements Logger {
+  StringBuffer _error = new StringBuffer();
+  StringBuffer _status = new StringBuffer();
+  StringBuffer _trace = new StringBuffer();
+
+  bool verbose = false;
+
+  String get errorText => _error.toString();
+  String get statusText => _status.toString();
+  String get traceText => _trace.toString();
+
+  void printError(String message, [StackTrace stackTrace]) => _error.writeln(message);
+  void printStatus(String message) => _status.writeln(message);
+  void printTrace(String message) => _trace.writeln(message);
+}
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart
index 7da7699..cac6702 100644
--- a/packages/flutter_tools/lib/src/base/process.dart
+++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -6,7 +6,7 @@
 import 'dart:convert';
 import 'dart:io';
 
-import 'context.dart';
+import 'globals.dart';
 
 typedef String StringConverter(String string);
 
diff --git a/packages/flutter_tools/lib/src/build_configuration.dart b/packages/flutter_tools/lib/src/build_configuration.dart
index 82a5bbb..160334b 100644
--- a/packages/flutter_tools/lib/src/build_configuration.dart
+++ b/packages/flutter_tools/lib/src/build_configuration.dart
@@ -6,7 +6,7 @@
 
 import 'package:path/path.dart' as path;
 
-import 'base/context.dart';
+import 'base/globals.dart';
 
 enum BuildType {
   prebuilt,
diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart
index 7d6742f..b50b90e 100644
--- a/packages/flutter_tools/lib/src/commands/analyze.dart
+++ b/packages/flutter_tools/lib/src/commands/analyze.dart
@@ -11,7 +11,7 @@
 import 'package:path/path.dart' as path;
 
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
 import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart
index 14070c9..f0f728f 100644
--- a/packages/flutter_tools/lib/src/commands/apk.dart
+++ b/packages/flutter_tools/lib/src/commands/apk.dart
@@ -12,8 +12,8 @@
 import '../android/device_android.dart';
 import '../application_package.dart';
 import '../artifacts.dart';
-import '../base/context.dart';
 import '../base/file_system.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
 import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart
index 1cfa1b0..5e1f763 100644
--- a/packages/flutter_tools/lib/src/commands/build.dart
+++ b/packages/flutter_tools/lib/src/commands/build.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../flx.dart';
 import '../runner/flutter_command.dart';
 import '../toolchain.dart';
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 60da5e5..f58bc77 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -11,7 +11,7 @@
 
 import '../android/android.dart' as android;
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 
 class CreateCommand extends Command {
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index 1656d8e..0dee7cc 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -9,6 +9,8 @@
 import '../android/adb.dart';
 import '../android/device_android.dart';
 import '../base/context.dart';
+import '../base/globals.dart';
+import '../base/logger.dart';
 import '../device.dart';
 import '../ios/device_ios.dart';
 import '../ios/simulator.dart';
@@ -33,9 +35,11 @@
   Future<int> runInProject() {
     printStatus('Starting device daemon...');
 
-    NotifyingAppContext appContext = new NotifyingAppContext();
+    AppContext appContext = new AppContext();
+    NotifyingLogger notifyingLogger = new NotifyingLogger();
+    appContext[Logger] = notifyingLogger;
 
-    return runZoned(() {
+    return appContext.runInZone(() {
       Stream<Map<String, dynamic>> commandStream = stdin
         .transform(UTF8.decoder)
         .transform(const LineSplitter())
@@ -47,10 +51,10 @@
 
       Daemon daemon = new Daemon(commandStream, (Map command) {
         stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
-      }, daemonCommand: this, appContext: appContext);
+      }, daemonCommand: this, notifyingLogger: notifyingLogger);
 
       return daemon.onExit;
-    }, zoneValues: {'context': appContext});
+    });
   }
 
   dynamic _jsonEncodeObject(dynamic object) {
@@ -67,7 +71,7 @@
 class Daemon {
   Daemon(Stream<Map> commandStream, this.sendCommand, {
     this.daemonCommand,
-    this.appContext
+    this.notifyingLogger
   }) {
     // Set up domains.
     _registerDomain(new DaemonDomain(this));
@@ -83,7 +87,7 @@
 
   final DispatchComand sendCommand;
   final DaemonCommand daemonCommand;
-  final NotifyingAppContext appContext;
+  final NotifyingLogger notifyingLogger;
 
   final Completer<int> _onExitCompleter = new Completer<int>();
   final Map<String, Domain> _domainMap = <String, Domain>{};
@@ -185,7 +189,7 @@
     registerHandler('version', version);
     registerHandler('shutdown', shutdown);
 
-    _subscription = daemon.appContext.onMessage.listen((LogMessage message) {
+    _subscription = daemon.notifyingLogger.onMessage.listen((LogMessage message) {
       if (message.stackTrace != null) {
         sendEvent('daemon.logMessage', {
           'level': message.level,
@@ -467,13 +471,11 @@
   return '$obj';
 }
 
-class NotifyingAppContext implements AppContext {
+class NotifyingLogger extends Logger {
   StreamController<LogMessage> _messageController = new StreamController<LogMessage>.broadcast();
 
   Stream<LogMessage> get onMessage => _messageController.stream;
 
-  bool verbose = false;
-
   void printError(String message, [StackTrace stackTrace]) {
     _messageController.add(new LogMessage('error', message, stackTrace));
   }
diff --git a/packages/flutter_tools/lib/src/commands/ios.dart b/packages/flutter_tools/lib/src/commands/ios.dart
index b424981..96f110a 100644
--- a/packages/flutter_tools/lib/src/commands/ios.dart
+++ b/packages/flutter_tools/lib/src/commands/ios.dart
@@ -8,7 +8,7 @@
 import "package:path/path.dart" as path;
 
 import "../artifacts.dart";
-import "../base/context.dart";
+import "../base/globals.dart";
 import "../base/process.dart";
 import "../runner/flutter_command.dart";
 import "../runner/flutter_command_runner.dart";
diff --git a/packages/flutter_tools/lib/src/commands/list.dart b/packages/flutter_tools/lib/src/commands/list.dart
index 885ba15..2eb0437 100644
--- a/packages/flutter_tools/lib/src/commands/list.dart
+++ b/packages/flutter_tools/lib/src/commands/list.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../device.dart';
 import '../runner/flutter_command.dart';
 
@@ -15,9 +15,7 @@
   bool get requiresProjectRoot => false;
 
   Future<int> runInProject() async {
-    DeviceManager deviceManager = new DeviceManager();
-
-    List<Device> devices = await deviceManager.getDevices();
+    List<Device> devices = await deviceManager.getAllConnectedDevices();
 
     if (devices.isEmpty) {
       printStatus('No connected devices.');
diff --git a/packages/flutter_tools/lib/src/commands/listen.dart b/packages/flutter_tools/lib/src/commands/listen.dart
index b139355..4fd76de 100644
--- a/packages/flutter_tools/lib/src/commands/listen.dart
+++ b/packages/flutter_tools/lib/src/commands/listen.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'dart:io';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import 'start.dart';
 
diff --git a/packages/flutter_tools/lib/src/commands/logs.dart b/packages/flutter_tools/lib/src/commands/logs.dart
index 0b274d3..3766de2 100644
--- a/packages/flutter_tools/lib/src/commands/logs.dart
+++ b/packages/flutter_tools/lib/src/commands/logs.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../device.dart';
 import '../runner/flutter_command.dart';
 
@@ -24,21 +24,14 @@
 
   Future<int> runInProject() async {
     DeviceManager deviceManager = new DeviceManager();
-    List<Device> devices;
+    deviceManager.specifiedDeviceId = globalResults['device-id'];
 
-    String deviceId = globalResults['device-id'];
-    if (deviceId != null) {
-      Device device = await deviceManager.getDeviceById(deviceId);
-      if (device == null) {
-        printError("No device found with id '$deviceId'.");
-        return 1;
-      }
-      devices = <Device>[device];
-    } else {
-      devices = await deviceManager.getDevices();
-    }
+    List<Device> devices = await deviceManager.getDevices();
 
-    if (devices.isEmpty) {
+    if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
+      printError("No device found with id '${deviceManager.specifiedDeviceId}'.");
+      return 1;
+    } else if (devices.isEmpty) {
       printStatus('No connected devices.');
       return 0;
     }
diff --git a/packages/flutter_tools/lib/src/commands/refresh.dart b/packages/flutter_tools/lib/src/commands/refresh.dart
index 02bb4d5..35ff972 100644
--- a/packages/flutter_tools/lib/src/commands/refresh.dart
+++ b/packages/flutter_tools/lib/src/commands/refresh.dart
@@ -7,7 +7,7 @@
 
 import 'package:path/path.dart' as path;
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../flx.dart';
 import '../runner/flutter_command.dart';
 
diff --git a/packages/flutter_tools/lib/src/commands/run_mojo.dart b/packages/flutter_tools/lib/src/commands/run_mojo.dart
index 9acffbc..77dc2a1 100644
--- a/packages/flutter_tools/lib/src/commands/run_mojo.dart
+++ b/packages/flutter_tools/lib/src/commands/run_mojo.dart
@@ -8,7 +8,7 @@
 import 'package:path/path.dart' as path;
 
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
 import '../flx.dart' as flx;
@@ -118,7 +118,7 @@
     if (useDevtools) {
       final String buildFlag = argResults['mojo-debug'] ? '--debug' : '--release';
       args.add(buildFlag);
-      if (context.verbose)
+      if (logger.verbose)
         args.add('--verbose');
     }
 
diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart
index ba653b0..9b9259e 100644
--- a/packages/flutter_tools/lib/src/commands/start.dart
+++ b/packages/flutter_tools/lib/src/commands/start.dart
@@ -9,7 +9,7 @@
 
 import '../application_package.dart';
 import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../build_configuration.dart';
 import '../device.dart';
 import '../flx.dart';
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 127391b..e7ebac2 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -9,7 +9,7 @@
 import 'package:test/src/executable.dart' as executable;
 
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../build_configuration.dart';
 import '../runner/flutter_command.dart';
 import '../test/loader.dart' as loader;
diff --git a/packages/flutter_tools/lib/src/commands/trace.dart b/packages/flutter_tools/lib/src/commands/trace.dart
index d66b741..a40af6d 100644
--- a/packages/flutter_tools/lib/src/commands/trace.dart
+++ b/packages/flutter_tools/lib/src/commands/trace.dart
@@ -6,7 +6,7 @@
 
 import '../android/device_android.dart';
 import '../application_package.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../runner/flutter_command.dart';
 
 class TraceCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart
index b9d249c..5e2a124 100644
--- a/packages/flutter_tools/lib/src/commands/upgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../runner/flutter_command.dart';
 import '../runner/version.dart';
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 460ade4..7c865b3 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -7,33 +7,48 @@
 import 'android/device_android.dart';
 import 'application_package.dart';
 import 'base/common.dart';
-import 'base/context.dart';
+import 'base/globals.dart';
 import 'build_configuration.dart';
 import 'ios/device_ios.dart';
 import 'toolchain.dart';
 
 /// A class to get all available devices.
 class DeviceManager {
+  /// Constructing DeviceManagers is cheap; they only do expensive work if some
+  /// of their methods are invoked.
   DeviceManager() {
-    // Init the known discoverers.
+    // Register the known discoverers.
     _deviceDiscoverers.add(new AndroidDeviceDiscovery());
     _deviceDiscoverers.add(new IOSDeviceDiscovery());
     _deviceDiscoverers.add(new IOSSimulatorDiscovery());
+  }
 
-    Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
-      if (!discoverer.supportsPlatform)
-        return null;
-      return discoverer.init();
-    }).then((_) {
-      _initedCompleter.complete();
-    }).catchError((error, stackTrace) {
-      _initedCompleter.completeError(error, stackTrace);
-    });
+  Future _init() {
+    if (_initedCompleter == null) {
+      _initedCompleter = new Completer();
+
+      Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
+        if (!discoverer.supportsPlatform)
+          return null;
+        return discoverer.init();
+      }).then((_) {
+        _initedCompleter.complete();
+      }).catchError((error, stackTrace) {
+        _initedCompleter.completeError(error, stackTrace);
+      });
+    }
+
+    return _initedCompleter.future;
   }
 
   List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[];
 
-  Completer _initedCompleter = new Completer();
+  /// A user-specified device ID.
+  String specifiedDeviceId;
+
+  Completer _initedCompleter;
+
+  bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
 
   /// Return the device with the matching ID; else, complete the Future with
   /// `null`.
@@ -41,15 +56,26 @@
   /// This does a case insentitive compare with `deviceId`.
   Future<Device> getDeviceById(String deviceId) async {
     deviceId = deviceId.toLowerCase();
-    List<Device> devices = await getDevices();
+    List<Device> devices = await getAllConnectedDevices();
     return devices.firstWhere(
       (Device device) => device.id.toLowerCase() == deviceId,
       orElse: () => null
     );
   }
 
+  /// Return the list of connected devices, filtered by any user-specified device id.
   Future<List<Device>> getDevices() async {
-    await _initedCompleter.future;
+    if (specifiedDeviceId == null) {
+      return getAllConnectedDevices();
+    } else {
+      Device device = await getDeviceById(specifiedDeviceId);
+      return device == null ? <Device>[] : <Device>[device];
+    }
+  }
+
+  /// Return the list of all connected devices.
+  Future<List<Device>> getAllConnectedDevices() async {
+    await _init();
 
     return _deviceDiscoverers
       .where((DeviceDiscovery discoverer) => discoverer.supportsPlatform)
diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart
index 2fb6efc..00973bc 100644
--- a/packages/flutter_tools/lib/src/flx.dart
+++ b/packages/flutter_tools/lib/src/flx.dart
@@ -13,7 +13,7 @@
 import 'package:path/path.dart' as path;
 import 'package:yaml/yaml.dart';
 
-import 'base/context.dart';
+import 'base/globals.dart';
 import 'base/file_system.dart';
 import 'toolchain.dart';
 
diff --git a/packages/flutter_tools/lib/src/ios/device_ios.dart b/packages/flutter_tools/lib/src/ios/device_ios.dart
index 321ef61..6ce1789 100644
--- a/packages/flutter_tools/lib/src/ios/device_ios.dart
+++ b/packages/flutter_tools/lib/src/ios/device_ios.dart
@@ -9,7 +9,7 @@
 
 import '../application_package.dart';
 import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
 import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/ios/simulator.dart b/packages/flutter_tools/lib/src/ios/simulator.dart
index eecd1af..f776382 100644
--- a/packages/flutter_tools/lib/src/ios/simulator.dart
+++ b/packages/flutter_tools/lib/src/ios/simulator.dart
@@ -6,7 +6,7 @@
 import 'dart:convert' show JSON;
 import 'dart:io';
 
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 
 const String _xcrunPath = '/usr/bin/xcrun';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 4df0131..2e94cbc 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -8,9 +8,9 @@
 import 'package:args/command_runner.dart';
 
 import '../application_package.dart';
-import '../base/context.dart';
-import '../build_configuration.dart';
 import '../artifacts.dart';
+import '../base/globals.dart';
+import '../build_configuration.dart';
 import '../device.dart';
 import '../toolchain.dart';
 import 'flutter_command_runner.dart';
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 65da945..a01c21f 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -10,7 +10,7 @@
 import 'package:path/path.dart' as path;
 
 import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
 import '../base/process.dart';
 import '../build_configuration.dart';
 import 'version.dart';
@@ -158,10 +158,15 @@
   }
 
   Future<int> runCommand(ArgResults globalResults) {
-    if (globalResults['verbose'])
-      context.verbose = true;
-
     _globalResults = globalResults;
+
+    // Check for verbose.
+    if (globalResults['verbose'])
+      logger.verbose = true;
+
+    // See if the user specified a specific device.
+    deviceManager.specifiedDeviceId = globalResults['device-id'];
+
     ArtifactStore.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root']));
     if (globalResults.wasParsed('package-root'))
       ArtifactStore.packageRoot = path.normalize(path.absolute(globalResults['package-root']));