perform the initial poll for devices quicker (#11356)

* perform the initial poll for devices quicker

* add a Poller class

* test the new Poller class
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index 31ee099..fddf40c 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -10,6 +10,7 @@
 import 'package:intl/intl.dart';
 import 'package:quiver/time.dart';
 
+import '../globals.dart';
 import 'context.dart';
 import 'file_system.dart';
 import 'platform.dart';
@@ -216,3 +217,42 @@
 }
 
 Clock get clock => context.putIfAbsent(Clock, () => const Clock());
+
+typedef Future<Null> AsyncCallback();
+
+/// A [Timer] inspired class that:
+///   - has a different initial value for the first callback delay
+///   - waits for a callback to be complete before it starts the next timer
+class Poller {
+  Poller(this.callback, this.pollingInterval, { this.initialDelay: Duration.ZERO }) {
+    new Future<Null>.delayed(initialDelay, _handleCallback);
+  }
+
+  final AsyncCallback callback;
+  final Duration initialDelay;
+  final Duration pollingInterval;
+
+  bool _cancelled = false;
+  Timer _timer;
+
+  Future<Null> _handleCallback() async {
+    if (_cancelled)
+      return;
+
+    try {
+      await callback();
+    } catch (error) {
+      printTrace('Error from poller: $error');
+    }
+
+    if (!_cancelled)
+      _timer = new Timer(pollingInterval, _handleCallback);
+  }
+
+  /// Cancels the poller.
+  void cancel() {
+    _cancelled = true;
+    _timer?.cancel();
+    _timer = null;
+  }
+}