Of everything in this section, this is the topic with the largest practical effect on your working day. Not the most glamorous — the most consequential.
The bottleneck it removes#
What a virtual ECU actually is#
A is the ECU's software running on a development machine instead of its target hardware, with the vehicle around it simulated.
The word covers four quite different things, and confusion between them causes real arguments. Be specific about which one you mean.
| Level | What is real | What is simulated | Speed | Good for |
|---|---|---|---|---|
| 1 — Application | Your application logic, compiled for the host | Everything below it | Instant | Logic, algorithms, unit tests |
| 2 — Platform | Application plus the real middleware stack | Hardware, bus, sensors | Seconds | Integration, API behaviour, most day-to-day work |
| 3 — Instruction | The actual target binary, on an emulated CPU | The chip and peripherals | Slow | Compiler and toolchain issues, memory layout |
| 4 — Cycle-accurate | Target binary with real timing | Everything, precisely | Very slow | Timing analysis, worst-case execution |
Gotcha
When someone says "we have virtual ECUs", ask which level. A level-1 vECU proves your algorithm is right. It proves nothing about whether your SOME/IP client handles a service going away mid-request. Teams have shipped bugs straight past a vECU suite that never exercised the layer containing them.
Software-in-the-loop, concretely#
SIL is one stage in a progression, and it is worth seeing where it sits before looking at how it is built.
SIL means the software under test runs against a simulated environment rather than physical hardware. For a cockpit team, a working setup looks like this:
┌─── your laptop ──────────────────────────────────────────────┐
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
│ │ Android │ │ Cluster │ │ Test scripts │ │
│ │ emulator (AAOS)│ │ renderer │ │ / pytest │ │
│ └───────┬────────┘ └───────┬────────┘ └───────┬───────┘ │
│ │ VHAL │ subscribe │ set │
│ └─────────┬──────────┴────────────────────┘ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ data broker (VSS) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ │ vehicle simulation │ ← drive cycles, faults, │
│ │ or recorded traces │ battery models │
│ └───────────────────────┘ │
└──────────────────────────────────────────────────────────────┘Where virtual stops being enough#
Being clear-eyed about this protects you from the failure mode where a team trusts simulation past its limits.
Building this on an Android programme#
Practical steps, roughly in order of value:
- Get a broker into the loop. Point the VHAL at a data broker behind a build flag, so the same APK runs against a vehicle or a simulator. This is the highest-value change and often the smallest.
- Model your properties in VSS. Even if the vehicle does not speak VSS, agreeing a signal vocabulary makes traces portable and tests readable.
- Record real drives. A library of captured traces — cold start, motorway, low battery, charging, fault injection — is worth more than any synthetic generator.
- Make scenarios files, not procedures. A YAML scenario in the repository can run in CI. A page of manual steps in a wiki cannot.
- Run it on every commit. A vECU suite that runs nightly catches things. One that runs per commit changes behaviour, because the feedback arrives while the author still has the context.
Gotcha
The trap is building an elaborate vehicle simulation nobody trusts. Fidelity is earned by comparing against recorded reality, repeatedly.
Start with replayed real traces, which are trustworthy by construction, and add synthetic models only where you have a reason and a way to validate them.
Next#
What to do with all that automated testing — continuous integration for vehicles.

