<# .SYNOPSIS Boots the Nuvolari Android emulator, unless one is already running. .DESCRIPTION Used as the preLaunchTask for the VS Code debug configurations, so pressing F5 works from a cold machine without a separate manual step. Idempotent on purpose: if a device is already attached the script returns immediately, so re-launching the debugger does not stack emulator instances. .PARAMETER Avd Name of the AVD to boot. Defaults to the one this project sets up. .PARAMETER TimeoutSeconds How long to wait for the boot to complete. Quickboot snapshots are disabled on this AVD to save disk, so a cold boot takes a minute or two. .EXAMPLE .\tool\start_emulator.ps1 #> [CmdletBinding()] param( [string]$Avd = 'nuvolari', [int]$TimeoutSeconds = 300 ) $ErrorActionPreference = 'Stop' $sdk = if ($env:ANDROID_HOME) { $env:ANDROID_HOME } elseif ($env:ANDROID_SDK_ROOT) { $env:ANDROID_SDK_ROOT } else { 'C:\Android\Sdk' } $adb = Join-Path $sdk 'platform-tools\adb.exe' $emulator = Join-Path $sdk 'emulator\emulator.exe' foreach ($tool in @($adb, $emulator)) { if (-not (Test-Path $tool)) { throw "Not found: $tool. Set ANDROID_HOME or install the Android SDK." } } function Get-AttachedDevice { # `adb devices` prints a header line, then "\tdevice" for each ready # device. Anything in another state (offline, unauthorized) does not count. $lines = & $adb devices 2>$null | Select-Object -Skip 1 foreach ($line in $lines) { if ($line -match '^(\S+)\s+device$') { return $Matches[1] } } return $null } $existing = Get-AttachedDevice if ($existing) { Write-Host "Device already attached: $existing" -ForegroundColor Green exit 0 } $available = & $emulator -list-avds 2>$null if ($available -notcontains $Avd) { throw "AVD '$Avd' does not exist. Available: $($available -join ', '). See docs/roadmap.md for how it was created." } Write-Host "Booting emulator '$Avd' (cold boot, snapshots are disabled)..." -ForegroundColor Cyan # Detached, with its own window, so the debug session does not own its lifetime # and stopping the debugger leaves the emulator up for the next run. Start-Process -FilePath $emulator ` -ArgumentList @('-avd', $Avd, '-no-audio', '-no-boot-anim', '-gpu', 'host') ` -WindowStyle Minimized | Out-Null $deadline = (Get-Date).AddSeconds($TimeoutSeconds) while ((Get-Date) -lt $deadline) { $device = Get-AttachedDevice if ($device) { $booted = (& $adb -s $device shell getprop sys.boot_completed 2>$null) -replace '\s', '' if ($booted -eq '1') { Write-Host "Emulator ready: $device" -ForegroundColor Green exit 0 } } Start-Sleep -Seconds 3 } throw "Emulator '$Avd' did not finish booting within $TimeoutSeconds seconds."