Expose emulator creation to daemon API (#18905)

* Fix typo

* Add emulator.create to Daemon API

* Swap order of daemon changelog entries
diff --git a/packages/flutter_tools/doc/daemon.md b/packages/flutter_tools/doc/daemon.md
index de847f9..e3e38a6 100644
--- a/packages/flutter_tools/doc/daemon.md
+++ b/packages/flutter_tools/doc/daemon.md
@@ -188,10 +188,22 @@
 
 #### emulator.launch
 
-The `launch()` command takes allows launching an emulator/simulator by its `id`.
+The `launch()` command allows launching an emulator/simulator by its `id`.
 
 - `emulatorId`: the id of an emulator as returned by `getEmulators`.
 
+#### emulator.create
+
+The `create()` command creates a new Android emulator with an optional `name`.
+
+- `name`: an optional name for this emulator
+
+The returned `params` will contain:
+
+- `success` - whether the emulator was successfully created
+- `emulatorName` - the name of the emulator created; this will have been auto-generated if you did not supply one
+- `error` - when `success`=`false`, a message explaining why the creation of the emulator failed
+
 ## Flutter Run --machine
 
 When running `flutter run --machine` the following subset of the daemon is available:
@@ -229,4 +241,5 @@
 
 ## Changelog
 
+- 0.4.0: Added `emulator.create` command
 - 0.3.0: Added `daemon.connected` event at startup
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index a675722..cf3a632 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -28,7 +28,7 @@
 import '../tester/flutter_tester.dart';
 import '../vmservice.dart';
 
-const String protocolVersion = '0.3.0';
+const String protocolVersion = '0.4.0';
 
 /// A server process command. This command will start up a long-lived server.
 /// It reads JSON-RPC based commands from stdin, executes them, and returns
@@ -849,6 +849,7 @@
   EmulatorDomain(Daemon daemon) : super(daemon, 'emulator') {
     registerHandler('getEmulators', getEmulators);
     registerHandler('launch', launch);
+    registerHandler('create', create);
   }
 
   Future<List<Map<String, dynamic>>> getEmulators([Map<String, dynamic> args]) async {
@@ -868,6 +869,16 @@
       await matches.first.launch();
     }
   }
+
+  Future<Map<String, dynamic>> create(Map<String, dynamic> args) async {
+    final String name = _getStringArg(args, 'name', required: false);
+    final CreateEmulatorResult res = await emulators.createEmulator(name: name);
+    return <String, dynamic>{
+      'success': res.success,
+      'emulatorName': res.emulatorName,
+      'error': res.error,
+    };
+  }
 }
 
 /// A [Logger] which sends log messages to a listening daemon client.
diff --git a/packages/flutter_tools/lib/src/emulator.dart b/packages/flutter_tools/lib/src/emulator.dart
index 472572c3..a860c42 100644
--- a/packages/flutter_tools/lib/src/emulator.dart
+++ b/packages/flutter_tools/lib/src/emulator.dart
@@ -98,12 +98,15 @@
     // - Removes lines that say "null" (!)
     // - Removes lines that tell the user to use '--force' to overwrite emulators
     String cleanError(String error) {
-      return (error ?? '')
+      if (error == null || error.trim() == '')
+        return null;
+      return error
           .split('\n')
           .where((String l) => l.trim() != 'null')
           .where((String l) =>
               l.trim() != 'Use --force if you want to replace it.')
-          .join('\n');
+          .join('\n')
+          .trim();
     }
 
     final List<String> args = <String>[