> ## Documentation Index
> Fetch the complete documentation index at: https://docs.macstadium.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Android Virtual Devices

> Run Android emulators natively on Apple silicon host nodes alongside MacStadium VDI macOS desktops, with automatic ADB connectivity to your VM.

Mobile developers using MacStadium VDI often need Android emulator access alongside their macOS desktop for testing, debugging, or running Android apps in parallel with their Citrix-managed session.

Android emulators cannot run inside a macOS virtual machine. The Apple Virtualization Framework does not support nested virtualization, so the emulator has no access to the hardware hypervisor it requires. Running an emulator inside a VM is not a supported path.

MacStadium VDI solves this by running the Android emulator natively on the Apple silicon host node, on the same physical machine as your macOS VM. An ADB relay is automatically configured between the host-side emulator and your VM, so your desktop session can reach the Android device over ADB without manual network setup or a third-party emulator service.

## Prerequisites

Before setting up Android Virtual Devices, ensure:

* MacStadium VDI is deployed and operational (see the [Deployment Guide](/remote-desktop-vdi/macstadium-vdi-deployment/deployment-guide))
* Ansible runner has `sshpass` installed
* The target macOS VM is running on a host node where the Android SDK will be installed

## Install the Android SDK

Run this on the Ansible runner to install the Android SDK on your host nodes. This installs:

* Homebrew (if not already present)
* Eclipse Temurin JDK 21
* Android command-line tools, platform-tools, and emulator packages
* `socat` (used to set up the ADB relay between the host and your VM)
* A `run-avd` script at `/opt/orka/bin/run-avd`

It also configures `JAVA_HOME`, `ANDROID_HOME`, and `PATH` in the host's `.zshrc`.

```bash theme={null}
ansible-playbook install_android_sdk.yml -i inventory
```

To force reinstallation on hosts where the SDK is already present:

```bash theme={null}
ansible-playbook install_android_sdk.yml -i inventory -e "install_android_sdk_force=true"
```

## Install SDK Platforms and System Images

Once the Android SDK is installed, install the platform and system images you want to use for your AVDs.

```bash theme={null}
ansible-playbook sdkmanager_install.yml -i inventory
```

This installs platform `android-35` with `default` and `google_apis` system images by default. To specify a different platform or image types:

```bash theme={null}
ansible-playbook sdkmanager_install.yml -i inventory -e "platform=android-34" -e "image_types=default,google_apis,google_apis_playstore"
```

Available variables:

* `platform` — Android platform to install (default: `android-35`)
* `image_types` — comma-separated list of system image types (default: `default,google_apis`)

## Create an Android Virtual Device

AVDs are tied to a specific VM. The AVD name is derived automatically from the VM name using the pattern `{vm_name}-avd-{index}`, where the index increments for each additional AVD on that VM (e.g. `my-vm-avd-0`, `my-vm-avd-1`).

Run with `--tags plan` first to preview which host the AVD will be created on:

```bash theme={null}
ansible-playbook deploy_avd.yml -i inventory -e "vm_name=my-vm" --tags plan
```

Then create the AVD:

```bash theme={null}
ansible-playbook deploy_avd.yml -i inventory -e "vm_name=my-vm"
```

The playbook locates the host running the specified VM, determines the next available AVD index, creates the AVD, and sets up network connectivity between the host-side emulator and the VM.

Available variables:

* `vm_name` *(required)* — name of the running VM the AVD should be associated with
* `platform` — Android platform to use (default: `android-35`)
* `image_type` — system image type (default: `default`)
* `run_avd` — whether to start the AVD immediately after creation (default: `true`)
* `cpu` — vCPUs to allocate to the AVD
* `memory` — memory in MB to allocate to the AVD

Example with custom settings:

```bash theme={null}
ansible-playbook deploy_avd.yml -i inventory -e "vm_name=my-vm" -e "platform=android-34" -e "image_type=google_apis" -e "cpu=4" -e "memory=2048"
```

## Manage Android Virtual Devices

### Start, stop, or delete an AVD

Use `avd.yml` to bring an AVD to a desired state. The playbook is idempotent - it will not attempt to start an already running AVD, stop an already stopped one, or delete one that does not exist.

```bash theme={null}
ansible-playbook avd.yml -i inventory -e "vm_name=my-vm" -e "desired_state=running"
```

Valid values for `desired_state`: `running`, `stopped`, `absent`

When only one AVD exists for a VM, it is selected automatically. If multiple AVDs exist, specify which one using `avd_index`:

```bash theme={null}
ansible-playbook avd.yml -i inventory -e "vm_name=my-vm" -e "desired_state=absent" -e "avd_index=1"
```

To preview the planned action without making changes:

```bash theme={null}
ansible-playbook avd.yml -i inventory -e "vm_name=my-vm" -e "desired_state=running" --tags plan
```

### List AVDs

To list all AVDs across all hosts:

```bash theme={null}
ansible-playbook list_avds.yml -i inventory
```

To filter by VM:

```bash theme={null}
ansible-playbook list_avds.yml -i inventory -e "vm_name=my-vm"
```

Each AVD is displayed with its host and status. Running AVDs include additional details: PID, gateway IP, and ADB relay port.

### Delete an AVD

To delete a specific AVD by index:

```bash theme={null}
ansible-playbook delete_avd.yml -i inventory -e "vm_name=my-vm" -e "avd_index=0"
```

If the AVD is currently running, the playbook stops it before deleting.

Required variables:

* `vm_name` — name of the VM the AVD is associated with
* `avd_index` — index of the AVD to delete (e.g. `0` for `my-vm-avd-0`)

## Uninstall SDK Platforms and System Images

To uninstall a specific platform and all of its system images from host nodes:

```bash theme={null}
ansible-playbook sdkmanager_uninstall.yml -i inventory
```

This uninstalls `android-35` by default. To target a different platform:

```bash theme={null}
ansible-playbook sdkmanager_uninstall.yml -i inventory -e "platform=android-34"
```
