Skip to content

Fix emulator boot and deploy flow for dotnet run#10969

Open
rmarinho wants to merge 8 commits intomainfrom
dev/ensure-device-booted-deploy
Open

Fix emulator boot and deploy flow for dotnet run#10969
rmarinho wants to merge 8 commits intomainfrom
dev/ensure-device-booted-deploy

Conversation

@rmarinho
Copy link
Member

@rmarinho rmarinho commented Mar 18, 2026

Summary

Running dotnet run --project <app>.csproj with a stopped Android emulator fails to boot the emulator and deploy the app, producing adb: no devices/emulators found or adb: device '<avd>' not found errors.

This PR fixes two issues in the emulator boot and deploy flow.

Fixes #10965

Problems & Fixes

1. _EnsureDeviceBooted not firing during DeployToDevice

The .NET SDK's dotnet run invokes DeployToDevice via ProjectInstance.Build(["DeployToDevice"]) in-process. In this execution mode, BeforeTargets hooks are not reliably triggered — only DependsOnTargets chains are respected.

Fix: Add _EnsureDeviceBooted to DeployToDeviceDependsOnTargets in BuildOrder.targets, and to _AndroidComputeRunArgumentsDependsOn in Application.targets, ensuring the emulator boots via the dependency chain during both the main build and the deploy step.

Note: A related issue where Device was not passed as a global property to the deploy step was fixed in the .NET SDK (dotnet/sdk#53018).

2. adb emu avd name returns empty on modern emulators

GetRunningAvdName used adb -s <serial> emu avd name to match running emulators to AVD names. On modern Android emulators (tested with emulator 36.4.10), this command returns zero bytes, causing the match to fail even when the correct emulator is already running.

Fix: Try adb shell getprop ro.boot.qemu.avd_name first (always set on emulators), falling back to emu avd name for older emulator versions.

Changes

  • Microsoft.Android.Sdk.Application.targets — Added _EnsureDeviceBooted to _AndroidComputeRunArgumentsDependsOn, simplified BeforeTargets to just _GetPrimaryCpuAbi (commercial builds), updated comments
  • Microsoft.Android.Sdk.BuildOrder.targets — Added _EnsureDeviceBooted to both DeployToDeviceDependsOnTargets variants
  • BootAndroidEmulator.cs — Fixed AVD name detection (getprop ro.boot.qemu.avd_name first, fallback to emu avd name)
  • BuildOrderTests.cs — Added DeployToDeviceDependsOn_ContainsEnsureDeviceBooted test

Testing

  • Unit test: DeployToDeviceDependsOn_ContainsEnsureDeviceBooted validates the target chain
  • Manual E2E: Verified on macOS with emulator 36.4.10, AVD MAUI_Emulator_API_36 (API 36), .NET 11 preview — emulator boots from cold, app deploys and launches with logcat streaming

Copy link
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem on the description sounds like:

Which should be in main, if you have at least:

@rmarinho rmarinho marked this pull request as ready for review March 18, 2026 20:37
Copilot AI review requested due to automatic review settings March 18, 2026 20:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes dotnet run --project <app>.csproj deploy failures when the selected Android emulator is stopped by ensuring the emulator-boot target runs via DependsOnTargets, and improving emulator detection/boot polling in the BootAndroidEmulator MSBuild task.

Changes:

  • Add _EnsureDeviceBooted into DeployToDeviceDependsOnTargets and _AndroidComputeRunArgumentsDependsOn so it runs reliably during in-proc ProjectInstance.Build(["DeployToDevice"]).
  • Improve AVD name detection by preferring adb shell getprop ro.boot.qemu.avd_name, with fallback to adb emu avd name.
  • Handle macOS emulator launcher “fork then exit 0” behavior by continuing to poll adb devices on exit code 0.
  • Add a unit test asserting _EnsureDeviceBooted is included in DeployToDeviceDependsOnTargets.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Application.targets Ensures _EnsureDeviceBooted participates in run-argument computation and clarifies execution rationale.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets Adds _EnsureDeviceBooted to deploy dependency chains (fast deploy + non-fast deploy).
src/Xamarin.Android.Build.Tasks/Tasks/BootAndroidEmulator.cs Updates AVD name detection and improves macOS emulator process exit handling.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildOrderTests.cs Adds coverage to validate deploy dependency chain includes _EnsureDeviceBooted.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 282 to +285
if (outputLines.Count > 0) {
var name = outputLines [0].Trim ();
if (!name.IsNullOrEmpty () && !name.Equals ("OK", StringComparison.OrdinalIgnoreCase)) {
avdName = name;
var consoleName = outputLines [0].Trim ();
if (!consoleName.IsNullOrEmpty () && !consoleName.Equals ("OK", StringComparison.OrdinalIgnoreCase)) {
avdName = consoleName;
@rmarinho rmarinho force-pushed the dev/ensure-device-booted-deploy branch 2 times, most recently from aa3f844 to d188a4b Compare March 19, 2026 16:27
@rmarinho rmarinho force-pushed the dev/ensure-device-booted-deploy branch from cf51ffd to 62a458e Compare March 19, 2026 18:40
rmarinho and others added 7 commits March 19, 2026 22:45
Address multiple issues preventing 'dotnet run --project' from
successfully booting an Android emulator and deploying the app.

Fixes: #10965

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add init.svc.bootanim check to WaitForFullBoot so we wait for the
  boot animation to stop before considering the emulator ready
- Detect 'used by another emulator' from stderr and fail fast with
  a clear error instead of silently timing out after 300 seconds
- Upgrade key milestone log messages to MessageImportance.High so
  users see progress during emulator boot (appeared online, system
  boot complete, fully ready) with elapsed times

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The dotnet/sdk fix (dotnet/sdk#53018) now properly passes the Device
global property to DeployToDevice via InvalidateGlobalProperties.
Remove the device.props write/read cache that was working around this.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove non-essential improvements (AVD lock detection, offline detection,
boot animation check, log message changes) to keep the diff minimal.
Only the three actual bug fixes remain: getprop AVD detection, fork
handling, and error reporting for non-zero exit codes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The emulator is already booted by ComputeAvailableDevices before
_EnsureDeviceBooted runs, so the task never launches a new emulator
process and the fork issue doesn't apply.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The DeployToDeviceDependsOnTargets property expands to multiple log
lines because it includes $(_MinimalSignAndroidPackageDependsOn).
The test was only checking the first line, which never contained
_EnsureDeviceBooted.

Switch to MSBuild property functions (Contains/IndexOf) to validate
directly in MSBuild, avoiding log parsing entirely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rmarinho rmarinho force-pushed the dev/ensure-device-booted-deploy branch from 62a458e to a2787ca Compare March 19, 2026 22:45
Keep the readable log-parsing approach (fixed by joining all output
lines for multi-line property matching) and add a separate MSBuild
property function test as a safety net.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

_EnsureDeviceBooted target does not fire during dotnet run deploy step

3 participants