Added emulator version to doctor (#167236)

fixes https://github.com/flutter/flutter/issues/146297

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 2dea1c3..9aefa8b 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -60,6 +60,43 @@
   bool get canListEmulators => canListDevices && _androidSdk?.emulatorPath != null;
 }
 
+Future<String?> getEmulatorVersion(AndroidSdk androidSdk, ProcessManager processManager) async {
+  if (!processManager.canRun(androidSdk.emulatorPath)) {
+    return null;
+  }
+
+  try {
+    final ProcessResult result = await processManager.run(<Object>[
+      androidSdk.emulatorPath!,
+      '-version',
+    ]);
+
+    if (result.exitCode != 0) {
+      return null;
+    }
+
+    final String output = result.stdout.toString().trim();
+
+    final String versionLine = output
+        .split('\n')
+        .firstWhere((String line) => line.contains('Android emulator version'), orElse: () => '');
+
+    if (versionLine.isNotEmpty) {
+      final RegExp regex = RegExp(r'Android emulator version\s+(.*)');
+      final Match? match = regex.firstMatch(versionLine);
+      if (match != null && match.groupCount >= 1) {
+        return match.group(1)?.trim();
+      } else {
+        return null;
+      }
+    } else {
+      return null;
+    }
+  } on Exception catch (e, _) {
+    return null;
+  }
+}
+
 /// A validator that checks if the Android SDK and Java SDK are available and
 /// installed correctly.
 ///
@@ -74,11 +111,13 @@
     required Logger logger,
     required Platform platform,
     required UserMessages userMessages,
+    required ProcessManager processManager,
   }) : _java = java,
        _androidSdk = androidSdk,
        _logger = logger,
        _platform = platform,
        _userMessages = userMessages,
+       _processManager = processManager,
        super('Android toolchain - develop for Android devices');
 
   final Java? _java;
@@ -86,6 +125,7 @@
   final Logger _logger;
   final Platform _platform;
   final UserMessages _userMessages;
+  final ProcessManager _processManager;
 
   @override
   String get slowWarning => '${_task ?? 'This'} is taking a long time...';
@@ -155,6 +195,11 @@
     }
 
     messages.add(ValidationMessage(_userMessages.androidSdkLocation(androidSdk.directory.path)));
+    messages.add(
+      ValidationMessage(
+        'Emulator version ${await getEmulatorVersion(androidSdk, _processManager) ?? 'unknown'}',
+      ),
+    );
 
     _task = 'Validating Android SDK command line tools are available';
     if (!androidSdk.cmdlineToolsAvailable) {
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 511c62c..78c74f8 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -121,6 +121,7 @@
             logger: globals.logger,
             platform: globals.platform,
             userMessages: globals.userMessages,
+            processManager: globals.processManager,
           ),
       AndroidWorkflow:
           () => AndroidWorkflow(androidSdk: globals.androidSdk, featureFlags: featureFlags),
diff --git a/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart b/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
index 57a2718..f3702eb 100644
--- a/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
@@ -425,12 +425,19 @@
     expect(stdio.writtenToStderr, contains('sdkmanager crash'));
   });
 
-  testWithoutContext('detects license-only SDK installation with cmdline-tools', () async {
+  testUsingContext('includes emulator version', () async {
     sdk
       ..licensesAvailable = true
       ..platformToolsAvailable = false
       ..cmdlineToolsAvailable = true
-      ..directory = fileSystem.directory('/foo/bar');
+      ..directory = fileSystem.directory('/foo/bar')
+      ..emulatorPath = 'path/to/emulator';
+    processManager.addCommand(
+      FakeCommand(
+        command: <String>[sdk.emulatorPath!, '-version'],
+        stdout: 'INFO    | Android emulator version 35.2.10.0 (build_id 12414864) (CL:N/A)',
+      ),
+    );
     final ValidationResult validationResult =
         await AndroidValidator(
           java: FakeJava(),
@@ -438,6 +445,31 @@
           logger: logger,
           platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
           userMessages: UserMessages(),
+          processManager: processManager,
+        ).validate();
+
+    expect(validationResult.type, ValidationType.partial);
+    expect(validationResult.messages.length > 2, isTrue);
+    final ValidationMessage sdkMessage = validationResult.messages[1];
+    expect(sdkMessage.type, ValidationMessageType.information);
+    expect(sdkMessage.message, 'Emulator version 35.2.10.0 (build_id 12414864) (CL:N/A)');
+  });
+
+  testUsingContext('detects license-only SDK installation with cmdline-tools', () async {
+    sdk
+      ..licensesAvailable = true
+      ..platformToolsAvailable = false
+      ..cmdlineToolsAvailable = true
+      ..directory = fileSystem.directory('/foo/bar')
+      ..emulatorPath = 'path/to/emulator';
+    final ValidationResult validationResult =
+        await AndroidValidator(
+          java: FakeJava(),
+          androidSdk: sdk,
+          logger: logger,
+          platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
+          userMessages: UserMessages(),
+          processManager: processManager,
         ).validate();
 
     expect(validationResult.type, ValidationType.partial);
@@ -464,7 +496,8 @@
       // Test with invalid SDK and build tools
       ..directory = fileSystem.directory('/foo/bar')
       ..sdkManagerPath = '/foo/bar/sdkmanager'
-      ..latestVersion = sdkVersion;
+      ..latestVersion = sdkVersion
+      ..emulatorPath = 'path/to/emulator';
 
     final String errorMessage = UserMessages().androidSdkBuildToolsOutdated(
       kAndroidSdkMinVersion,
@@ -478,6 +511,7 @@
       logger: logger,
       platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
       userMessages: UserMessages(),
+      processManager: processManager,
     );
 
     ValidationResult validationResult = await androidValidator.validate();
@@ -505,12 +539,13 @@
     );
   });
 
-  testWithoutContext('detects missing cmdline tools', () async {
+  testUsingContext('detects missing cmdline tools', () async {
     sdk
       ..licensesAvailable = true
       ..platformToolsAvailable = true
       ..cmdlineToolsAvailable = false
-      ..directory = fileSystem.directory('/foo/bar');
+      ..directory = fileSystem.directory('/foo/bar')
+      ..emulatorPath = 'path/to/emulator';
 
     final AndroidValidator androidValidator = AndroidValidator(
       java: FakeJava(),
@@ -518,6 +553,7 @@
       logger: logger,
       platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
       userMessages: UserMessages(),
+      processManager: processManager,
     );
 
     final ValidationResult validationResult = await androidValidator.validate();
@@ -558,7 +594,8 @@
       ..platformToolsAvailable = true
       ..cmdlineToolsAvailable = true
       ..directory = fileSystem.directory('/foo/bar')
-      ..sdkManagerPath = '/foo/bar/sdkmanager';
+      ..sdkManagerPath = '/foo/bar/sdkmanager'
+      ..emulatorPath = 'path/to/emulator';
     sdk.latestVersion = sdkVersion;
 
     const String javaVersionText = 'openjdk version "1.7.0_212"';
@@ -571,6 +608,7 @@
           logger: logger,
           platform: platform,
           userMessages: UserMessages(),
+          processManager: processManager,
         ).validate();
     expect(validationResult.type, ValidationType.partial);
     expect(validationResult.messages.last.message, errorMessage);
@@ -595,6 +633,7 @@
                   Java.javaHomeEnvironmentVariable: 'home/java',
                 },
           userMessages: UserMessages(),
+          processManager: processManager,
         ).validate();
 
     expect(
@@ -646,46 +685,45 @@
     },
   );
 
-  testWithoutContext(
-    'Mentions that JDK is provided by latest Android Studio Installation',
-    () async {
-      // Mock a pass through scenario to reach _checkJavaVersion()
-      sdk
-        ..licensesAvailable = true
-        ..platformToolsAvailable = true
-        ..cmdlineToolsAvailable = true
-        ..directory = fileSystem.directory('/foo/bar')
-        ..sdkManagerPath = '/foo/bar/sdkmanager';
+  testUsingContext('Mentions that JDK is provided by latest Android Studio Installation', () async {
+    // Mock a pass through scenario to reach _checkJavaVersion()
+    sdk
+      ..licensesAvailable = true
+      ..platformToolsAvailable = true
+      ..cmdlineToolsAvailable = true
+      ..directory = fileSystem.directory('/foo/bar')
+      ..sdkManagerPath = '/foo/bar/sdkmanager'
+      ..emulatorPath = 'path/to/emulator';
 
-      final ValidationResult validationResult =
-          await AndroidValidator(
-            java: FakeJava(),
-            androidSdk: sdk,
-            logger: logger,
-            platform: FakePlatform(),
-            userMessages: UserMessages(),
-          ).validate();
+    final ValidationResult validationResult =
+        await AndroidValidator(
+          java: FakeJava(),
+          androidSdk: sdk,
+          logger: logger,
+          platform: FakePlatform(),
+          userMessages: UserMessages(),
+          processManager: processManager,
+        ).validate();
 
-      expect(
-        validationResult.messages.any(
-          (ValidationMessage message) => message.message.contains(
-            'This is the JDK bundled with the latest Android Studio installation on this machine.',
-          ),
+    expect(
+      validationResult.messages.any(
+        (ValidationMessage message) => message.message.contains(
+          'This is the JDK bundled with the latest Android Studio installation on this machine.',
         ),
-        true,
-      );
-      expect(
-        validationResult.messages.any(
-          (ValidationMessage message) => message.message.contains(
-            'To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.',
-          ),
+      ),
+      true,
+    );
+    expect(
+      validationResult.messages.any(
+        (ValidationMessage message) => message.message.contains(
+          'To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.',
         ),
-        true,
-      );
-    },
-  );
+      ),
+      true,
+    );
+  });
 
-  testWithoutContext(
+  testUsingContext(
     "Mentions that JDK is provided by user's JAVA_HOME environment variable",
     () async {
       // Mock a pass through scenario to reach _checkJavaVersion()
@@ -694,7 +732,8 @@
         ..platformToolsAvailable = true
         ..cmdlineToolsAvailable = true
         ..directory = fileSystem.directory('/foo/bar')
-        ..sdkManagerPath = '/foo/bar/sdkmanager';
+        ..sdkManagerPath = '/foo/bar/sdkmanager'
+        ..emulatorPath = 'path/to/emulator';
 
       final ValidationResult validationResult =
           await AndroidValidator(
@@ -703,6 +742,7 @@
             logger: logger,
             platform: FakePlatform(),
             userMessages: UserMessages(),
+            processManager: processManager,
           ).validate();
 
       expect(
@@ -724,14 +764,15 @@
     },
   );
 
-  testWithoutContext('Mentions that path to Java binary is obtained from PATH', () async {
+  testUsingContext('Mentions that path to Java binary is obtained from PATH', () async {
     // Mock a pass through scenario to reach _checkJavaVersion()
     sdk
       ..licensesAvailable = true
       ..platformToolsAvailable = true
       ..cmdlineToolsAvailable = true
       ..directory = fileSystem.directory('/foo/bar')
-      ..sdkManagerPath = '/foo/bar/sdkmanager';
+      ..sdkManagerPath = '/foo/bar/sdkmanager'
+      ..emulatorPath = 'path/to/emulator';
 
     final ValidationResult validationResult =
         await AndroidValidator(
@@ -740,6 +781,7 @@
           logger: logger,
           platform: FakePlatform(),
           userMessages: UserMessages(),
+          processManager: processManager,
         ).validate();
 
     expect(
@@ -759,14 +801,15 @@
     );
   });
 
-  testWithoutContext('Mentions that JDK is provided by Flutter config', () async {
+  testUsingContext('Mentions that JDK is provided by Flutter config', () async {
     // Mock a pass through scenario to reach _checkJavaVersion()
     sdk
       ..licensesAvailable = true
       ..platformToolsAvailable = true
       ..cmdlineToolsAvailable = true
       ..directory = fileSystem.directory('/foo/bar')
-      ..sdkManagerPath = '/foo/bar/sdkmanager';
+      ..sdkManagerPath = '/foo/bar/sdkmanager'
+      ..emulatorPath = 'path/to/emulator';
 
     final ValidationResult validationResult =
         await AndroidValidator(
@@ -775,6 +818,7 @@
           logger: logger,
           platform: FakePlatform(),
           userMessages: UserMessages(),
+          processManager: processManager,
         ).validate();
 
     expect(