Register flutterVersion service in flutter_tools. (#39524)

* Register getFlutterVersion service in flutter_tools.

* Add short revision ids to response.

* Rename method and remove obsolete comments.

* Fix broken test by adding sendPeerNotifications flag.

* Implement mockPeer.sendNotification.
diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart
index a3de239..03a8ef3 100644
--- a/packages/flutter_tools/lib/src/vmservice.dart
+++ b/packages/flutter_tools/lib/src/vmservice.dart
@@ -20,6 +20,7 @@
 import 'base/utils.dart';
 import 'convert.dart' show base64;
 import 'globals.dart';
+import 'version.dart';
 import 'vmservice_record_replay.dart';
 
 /// Override `WebSocketConnector` in [context] to use a different constructor
@@ -138,8 +139,6 @@
         }
       });
 
-      // If the Flutter Engine doesn't support service registration this will
-      // have no effect
       _peer.sendNotification('registerService', <String, String>{
         'service': 'reloadSources',
         'alias': 'Flutter Tools',
@@ -164,14 +163,25 @@
         }
       });
 
-      // If the Flutter Engine doesn't support service registration this will
-      // have no effect
       _peer.sendNotification('registerService', <String, String>{
         'service': 'hotRestart',
         'alias': 'Flutter Tools',
       });
     }
 
+    _peer.registerMethod('flutterVersion', (rpc.Parameters params) async {
+      final FlutterVersion version = FlutterVersion();
+      final Map<String, Object> versionJson = version.toJson();
+      versionJson['frameworkRevisionShort'] = version.frameworkRevisionShort;
+      versionJson['engineRevisionShort'] = version.engineRevisionShort;
+      return versionJson;
+    });
+
+    _peer.sendNotification('registerService', <String, String>{
+      'service': 'flutterVersion',
+      'alias': 'Flutter Tools',
+    });
+
     if (compileExpression != null) {
       _peer.registerMethod('compileExpression', (rpc.Parameters params) async {
         final String isolateId = params['isolateId'].asString;
diff --git a/packages/flutter_tools/test/general.shard/vmservice_test.dart b/packages/flutter_tools/test/general.shard/vmservice_test.dart
index ccf816b..308b4c8 100644
--- a/packages/flutter_tools/test/general.shard/vmservice_test.dart
+++ b/packages/flutter_tools/test/general.shard/vmservice_test.dart
@@ -52,9 +52,12 @@
 
   @override
   void sendNotification(String method, [ dynamic parameters ]) {
-    throw 'unexpected call to sendNotification';
+    // this does get called
+    sentNotifications.putIfAbsent(method, () => <dynamic>[]).add(parameters);
   }
 
+  Map<String, List<dynamic>> sentNotifications = <String, List<dynamic>>{};
+
   bool isolatesEnabled = false;
 
   Future<void> _getVMLatch;
@@ -192,6 +195,12 @@
         final MockPeer mockPeer = MockPeer();
         expect(mockPeer.returnedFromSendRequest, 0);
         final VMService vmService = VMService(mockPeer, null, null, null, null, null);
+        expect(mockPeer.sentNotifications, contains('registerService'));
+        final List<String> registeredServices =
+          mockPeer.sentNotifications['registerService']
+            .map((dynamic service) => (service as Map<String, String>)['service'])
+            .toList();
+        expect(registeredServices, contains('flutterVersion'));
         vmService.getVM().then((void value) { done = true; });
         expect(done, isFalse);
         expect(mockPeer.returnedFromSendRequest, 0);