EmulatorRunner: return serial / console port / adb port / log path from launch
- Dominant language
- C#
- Stars
- 2.1k
- Forks
- 579
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 257
Description
## Context
Xamarin.Android.Tools.EmulatorRunner.LaunchEmulator(name, coldBoot) returns a bare System.Diagnostics.Process. Callers (e.g. `dotnet/maui-labs` `maui android emulator start` — see https://github.com/dotnet/maui-labs/issues/138) want to surface to users / scripts:
- The emulator **serial** (`emulator-NNNN`).
- The **console port** and **adb port**.
- The **log file path** the emulator writes to.
Today none of this is available from `EmulatorRunner` without out-of-band work:
- Serial / ports → caller has to diff `adb devices` before/after launch (race-prone, requires waiting for adb to see it, breaks fire-and-forget mode).
- Log path → caller has to hardcode the AOSP convention (`\/.avd/emulator.log` or `\C:\Users\rumar/.android/avd/.avd/emulator.log`) — fine until the emulator is launched with `-logfile` or a custom `ANDROID_AVD_HOME`.
This duplicates logic in every consumer and is fragile. The data is all available to `EmulatorRunner` itself — the emulator prints serial/port info to stdout at boot, and `EmulatorRunner` controls the launch arg list.
## Proposal
### 1. Richer launch result
Introduce a new return type and overload (keep existing `LaunchEmulator` signature for compatibility):
```csharp
public sealed class EmulatorLaunchResult
{
public Process Process { get; init; }
public int Pid => Process.Id;
public int? ConsolePort { get; init; } // populated once stdout is parsed (or pre-assigned)
public int? AdbPort { get; init; }
public string? Serial => ConsolePort is int p ? \$"emulator-{p}" : null;
public string LogPath { get; init; } // resolved at launch time
public Task PortsResolvedAsync { get; init; } // completes when stdout parse finds the port lines
}
public EmulatorLaunchResult LaunchEmulatorWithDetails(
string avdName,
bool coldBoot = false,
int? consolePort = null, // optional pre-assignment via -ports
int? adbPort = null,
string? logFile = null);
```
### 2. Pre-assigned ports (optional but recommended)
When `consolePort` is passed, `EmulatorRunner` adds `-ports ,` to the qemu command line. This lets callers know the serial **before the process even starts** — no stdout race, no adb diff. AOSP supports console ports 5554–5682 in steps of 2.
If not passed, `EmulatorRunner` reserves a free pair itself (probe + bind) or falls back to stdout parsing.
### 3. Stdout capture for late binding
When ports are not pre-assigned, `EmulatorRunner` should redirect stdout (it likely already does for diagnostics) and parse the well-known lines the emulator emits at boot:
`
emulator: Listening on port
emulator: ADB Server has started successfully on port
emulator: Logs in
`
These complete the `PortsResolvedAsync` task. Format has been stable across `emulator` releases for years; if it shifts, only this one place changes.
### 4. `BootEmulatorAsync` returns the same shape
`BootEmulatorAsync` (the wait-for-boot path) should return `EmulatorLaunchResult` enriched with `Serial` always populated (since by definition adb has seen it), instead of the current opaque result.
## Compatibility
- Existing `LaunchEmulator` / `BootEmulatorAsync` signatures **stay** — additive only.
- New entry points are `LaunchEmulatorWithDetails` and a `BootEmulatorWithDetailsAsync` overload (or extend the existing result type with new optional members).
- `EmulatorLaunchResult` is a new public type.
## Why this matters
- Eliminates the race in every downstream tool that pairs `maui device list` against `maui android emulator start`.
- Makes `maui android emulator start --json` a complete, scriptable response (matches the new Google `android emulator start` CLI shape: log path + pid + serial + status).
- Enables non-`--wait` launches to still return a serial — currently impossible without polling.
- Removes the need for downstream tools to scavenge `\/running/pid_*.ini` to figure out which qemu PID maps to which emulator (see `dotnet/maui-labs#135`).
## Related
- `dotnet/maui-labs#138` — consumer-side enhancement that benefits directly.
- `dotnet/maui-labs#135` — pid-file based liveness (avoidable for emulators we launched ourselves once this lands).
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.