FAQ¶
Do I need special hardware?¶
No. The default emulationBackend: cuttlefish-qemu runs the Android device using QEMU software emulation inside an ordinary container. No KVM device, no kernel modules, no node labels, and no privileged DaemonSets are required.
Any standard Kubernetes node — including cloud-managed node pools and spot instances — works out of the box. You only need to prepare nodes if you want hardware acceleration. See Hardware Acceleration for details.
How do I access the device from a browser?¶
Each TestSession exposes status.streamURL once it reaches Running. The DroidFarm dashboard embeds the Cuttlefish WebRTC stream in an iframe so you can watch the device screen directly in your browser — no client software, VNC client, or plugin needed.
At the pool level, each device entry in status.devices also carries a streamURL.
Retrieve the URL for an active session:
How do I connect my Appium tests?¶
Once a TestSession reaches Running, read status.appiumEndpoint:
APPIUM_URL=$(kubectl get testsession <name> -n droidfarm-system \
-o jsonpath='{.status.appiumEndpoint}')
Pass that URL as the command_executor in your Appium client:
See the Testing Guide for a full working example and CI integration.
How many devices can I run in parallel?¶
As many as your cluster can schedule. The limit is the replicas.max field of your DevicePool. Each device pod requires at minimum 2 CPU cores and 4 Gi of memory (enforced by the LimitRange in droidfarm-system).
Enable KEDA autoscaling to scale device count automatically in response to pending TestSession demand:
helm upgrade droidfarm droidfarm/droidfarm \
--namespace droidfarm-system \
--reuse-values \
--set keda.enabled=true
How do I install apps on the device?¶
Define appConfig entries in your DeviceTemplate. The operator's apk-installer init container downloads and installs each APK via ADB before the device transitions to Idle, so every claimed device already has your app installed:
spec:
appConfig:
- packageName: com.example.myapp
apkSource:
url: https://artifacts.example.com/app.apk
autoLaunch: true
clearDataBetweenSessions: true
The first entry is the primary app under test. Additional entries are companion apps installed alongside it. See CRD Reference for the full appConfig field list.
What Android versions are supported?¶
Android 13, 14, and 15 (API levels 33, 34, and 35). Specify the version in the DeviceTemplate:
How do I get the device screen recording?¶
After the session reaches Succeeded or Failed, check status.artifactURL. The operator uploads recordings to S3 (if artifacts.s3 is configured in your TestSession) or to a PVC.
You can also use the CLI to retrieve artifact location information:
If status.artifactURL is set, the command prints a curl download command. If the session pod is still present, it prints a kubectl cp command to copy recordings directly from the pod.
Configure artifact storage in your TestSession:
Can I run multiple tests in parallel?¶
Yes. Create one TestSession per parallel test worker. The operator claims one device per session. Set replicas.max in your DevicePool to the desired maximum concurrency:
For pytest with pytest-xdist, create one TestSession per worker, pass each status.appiumEndpoint as an environment variable, and use --dist=loadfile to keep stateful tests on the same worker. See Testing Guide for the full parallel execution pattern.
How do I get faster boot times?¶
Use emulationBackend: cuttlefish (without -qemu) in your DeviceTemplate. This enables KVM hardware-accelerated virtualization and reduces boot time from approximately 5–10 minutes to approximately 60 seconds.
This requires KVM-capable nodes. See Hardware Acceleration for node preparation steps and cloud provider instance type recommendations.
Alternatively, keep replicas.min >= 1 so at least one warm device is always ready in the pool — test sessions claim an already-booted device instantly.
What happens when a session times out?¶
The operator transitions the session to TimedOut, releases the device back to the pool (device phase returns to Idle), and increments the SessionsServed counter on the DevicePool. The status.failureMessage field on the session is set to indicate the timeout.
The session's status.endTime and status.duration are recorded. If artifact collection was enabled, the operator attempts to save any partial recordings before releasing the device.
To avoid timeouts, set a realistic timeout in your TestSession spec (default is 1h) and use droidfarm watch-session <name> to observe phase transitions in real time.