Make initial daemon devices population fast (#56959)

diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 61d46ff..cef0855 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -297,19 +297,21 @@
   void startPolling() {
     if (_timer == null) {
       _items ??= ItemListNotifier<Device>();
-      _timer = _initTimer();
+      // Make initial population the default, fast polling timeout.
+      _timer = _initTimer(null);
     }
   }
 
-  Timer _initTimer() {
+  Timer _initTimer(Duration pollingTimeout) {
     return Timer(_pollingInterval, () async {
       try {
-        final List<Device> devices = await pollingGetDevices(timeout: _pollingTimeout);
+        final List<Device> devices = await pollingGetDevices(timeout: pollingTimeout);
         _items.updateWithNewList(devices);
       } on TimeoutException {
         globals.printTrace('Device poll timed out. Will retry.');
       }
-      _timer = _initTimer();
+      // Subsequent timeouts after initial population should wait longer.
+      _timer = _initTimer(_pollingTimeout);
     });
   }
 
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
index 2520562..7b37797 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
@@ -194,7 +194,7 @@
         responses.add,
         notifyingLogger: notifyingLogger,
       );
-      final MockPollingDeviceDiscovery discoverer = MockPollingDeviceDiscovery();
+      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
       daemon.deviceDomain.addDeviceDiscoverer(discoverer);
       discoverer.addDevice(MockAndroidDevice());
       commands.add(<String, dynamic>{'id': 0, 'method': 'device.getDevices'});
@@ -216,7 +216,7 @@
         notifyingLogger: notifyingLogger,
       );
 
-      final MockPollingDeviceDiscovery discoverer = MockPollingDeviceDiscovery();
+      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
       daemon.deviceDomain.addDeviceDiscoverer(discoverer);
       discoverer.addDevice(MockAndroidDevice());
 
diff --git a/packages/flutter_tools/test/general.shard/device_test.dart b/packages/flutter_tools/test/general.shard/device_test.dart
index 42a0131..bad20c2 100644
--- a/packages/flutter_tools/test/general.shard/device_test.dart
+++ b/packages/flutter_tools/test/general.shard/device_test.dart
@@ -9,6 +9,7 @@
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/project.dart';
 import 'package:mockito/mockito.dart';
+import 'package:quiver/testing/async.dart';
 
 import '../src/common.dart';
 import '../src/context.dart';
@@ -63,6 +64,26 @@
     });
   });
 
+  group('PollingDeviceDiscovery', () {
+    testUsingContext('startPolling', () async {
+      FakeAsync().run((FakeAsync time) {
+        final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery();
+        pollingDeviceDiscovery.startPolling();
+        time.elapse(const Duration(milliseconds: 4001));
+        time.flushMicrotasks();
+        // First check should use the default polling timeout
+        // to quickly populate the list.
+        expect(pollingDeviceDiscovery.lastPollingTimeout, isNull);
+
+        time.elapse(const Duration(milliseconds: 4001));
+        time.flushMicrotasks();
+        // Subsequent polling should be much longer.
+        expect(pollingDeviceDiscovery.lastPollingTimeout, const Duration(seconds: 30));
+        pollingDeviceDiscovery.stopPolling();
+      });
+    });
+  });
+
   group('Filter devices', () {
     FakeDevice ephemeral;
     FakeDevice nonEphemeralOne;
@@ -198,12 +219,12 @@
 
 class TestDeviceManager extends DeviceManager {
   TestDeviceManager(List<Device> allDevices) {
-    _deviceDiscoverer = MockPollingDeviceDiscovery();
+    _deviceDiscoverer = FakePollingDeviceDiscovery();
     resetDevices(allDevices);
   }
   @override
   List<DeviceDiscovery> get deviceDiscoverers => <DeviceDiscovery>[_deviceDiscoverer];
-  MockPollingDeviceDiscovery _deviceDiscoverer;
+  FakePollingDeviceDiscovery _deviceDiscoverer;
 
   void resetDevices(List<Device> allDevices) {
     _deviceDiscoverer.setDevices(allDevices);
diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
index 3ababad..5f69d05 100644
--- a/packages/flutter_tools/test/src/mocks.dart
+++ b/packages/flutter_tools/test/src/mocks.dart
@@ -482,8 +482,8 @@
   List<String> get writtenToStderr => _stderr.writes.map<String>(_stderr.encoding.decode).toList();
 }
 
-class MockPollingDeviceDiscovery extends PollingDeviceDiscovery {
-  MockPollingDeviceDiscovery() : super('mock');
+class FakePollingDeviceDiscovery extends PollingDeviceDiscovery {
+  FakePollingDeviceDiscovery() : super('mock');
 
   final List<Device> _devices = <Device>[];
   final StreamController<Device> _onAddedController = StreamController<Device>.broadcast();