Add EmulatorRunner for emulator CLI operations#284
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new EmulatorRunner to Xamarin.Android.Tools.AndroidSdk intended to wrap Android emulator CLI operations, alongside new shared infrastructure for running Android SDK command-line tools with environment setup and result modeling.
Changes:
- Added
EmulatorRunnerto start an AVD, stop an emulator, and list available AVD names. - Added
AndroidToolRunnerutility to run SDK tools sync/async (with timeouts) and to start long-running background processes. - Added
AndroidEnvironmentHelperandToolRunnerResult/ToolRunnerResult<T>to standardize tool environment and execution results.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| src/Xamarin.Android.Tools.AndroidSdk/Runners/EmulatorRunner.cs | Introduces emulator wrapper methods (start/stop/list AVDs) built on the tool runner infrastructure. |
| src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidToolRunner.cs | Adds process execution helpers (sync/async + background) with timeout/output capture. |
| src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidEnvironmentHelper.cs | Adds env var setup and mapping helpers (ABI/API/tag display names). |
| src/Xamarin.Android.Tools.AndroidSdk/Models/ToolRunnerResult.cs | Adds a shared result model for tool execution. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidEnvironmentHelper.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidEnvironmentHelper.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidToolRunner.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidToolRunner.cs
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Tools.AndroidSdk/Runners/AndroidToolRunner.cs
Outdated
Show resolved
Hide resolved
|
I'd like to get the System.Diagnostics.Process code unified like mentioned here: |
Addresses PR #284 feedback to use existing ProcessUtils instead of the removed AndroidToolRunner. Simplifies API: - Methods now throw InvalidOperationException on failure - Uses ProcessUtils.RunToolAsync() and StartToolBackground() - Removed complex ToolRunnerResult wrapper types Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
f1aa44f to
826d4aa
Compare
Addresses PR #283/#284 feedback to use existing ProcessUtils. Simplifies API by throwing exceptions on failure instead of returning result types with error states. Changes: - AdbRunner: Simplified using ProcessUtils.RunToolAsync() - EmulatorRunner: Uses ProcessUtils.StartToolBackground() - Removed duplicate AndroidDeviceInfo from Models directory Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
39617c8 to
5268300
Compare
| /// Runs Android Emulator commands. | ||
| /// </summary> | ||
| public class EmulatorRunner | ||
| { | ||
| readonly Func<string?> getSdkPath; |
There was a problem hiding this comment.
PR description/New API lists StartEmulator/StartEmulatorAsync, WaitForBootAsync, and ListRunningEmulatorsAsync, but this class currently only implements StartAvd and ListAvdNamesAsync (and the signature differs). Either update the implementation to match the proposed API surface or adjust the PR description/issue link expectations so consumers aren’t broken/misled.
| var args = $"-avd \"{avdName}\""; | ||
| if (coldBoot) | ||
| args += " -no-snapshot-load"; | ||
| if (!string.IsNullOrEmpty (additionalArgs)) | ||
| args += " " + additionalArgs; |
There was a problem hiding this comment.
StartAvd builds a single argument string by interpolating avdName and appending additionalArgs verbatim. If avdName contains quotes/whitespace (or additionalArgs comes from untrusted input), this can break parsing or allow argument injection. Consider validating/escaping avdName (e.g., reject quotes) and taking additional args as a structured list (e.g., IEnumerable) with proper quoting/escaping when constructing Arguments.
| if (!IsAvailable) | ||
| throw new InvalidOperationException ("Android Emulator not found."); | ||
|
|
||
| var stdout = new StringWriter (); |
There was a problem hiding this comment.
ListAvdNamesAsync allocates a StringWriter for stdout but never disposes it. Use a using/using var to dispose the writer (and to keep the pattern consistent with other code that disposes disposable resources).
| var stdout = new StringWriter (); | |
| using var stdout = new StringWriter (); |
| /// <param name="cancellationToken">Cancellation token.</param> | ||
| /// <returns>A list of AVD names.</returns> | ||
| /// <exception cref="InvalidOperationException">Thrown when Android Emulator is not found.</exception> | ||
| public async Task<List<string>> ListAvdNamesAsync (CancellationToken cancellationToken = default) |
There was a problem hiding this comment.
Public API returns Task<List>, which exposes a mutable concrete collection. Consider returning Task<IReadOnlyList> (or IReadOnlyList) to avoid leaking mutability and to align with the API shape described in the PR metadata.
| public async Task<List<string>> ListAvdNamesAsync (CancellationToken cancellationToken = default) | |
| public async Task<IReadOnlyList<string>> ListAvdNamesAsync (CancellationToken cancellationToken = default) |
- StartAvd(): Start an emulator for an AVD - ListAvdNamesAsync(): List installed AVD names Minimal implementation without external dependencies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add XML documentation to all public members - Use 'is not null' instead of '!= null' - Improve code formatting - Remove unused variable assignment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add optional Func<string?> getJdkPath constructor parameter - ConfigureEnvironment() sets JAVA_HOME and ANDROID_HOME on all ProcessStartInfo - Applied to StartAvd and ListAvdNamesAsync - Backward compatible: existing 1-arg constructor still works Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4957925 to
9b53526
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Wraps
emulatorCLI operations for starting and managing Android emulators. Addresses #278.Changes
New constructor overload with JDK path
public EmulatorRunner (Func<string?> getSdkPath, Func<string?>? getJdkPath)Sets JAVA_HOME and ANDROID_HOME on all child process ProcessStartInfo via ConfigureEnvironment().
The existing 1-arg constructor remains backward compatible.
Updated: StartAvd / ListAvdNamesAsync
Now call ConfigureEnvironment(psi) before starting processes.
API
Dependencies
Requires #283 (AdbRunner) for the adb-runner branch.