Beroun does not know what device it runs on. Everything device-specific sits behind a small set of interfaces, each with a system implementation and a test double. A device, a simulator or a phone supplies the interfaces, and the apps, Caroline and the store don't change.
The interfaces
| Interface | In the code | In the simulator | On a device |
|---|---|---|---|
| Input and sensors | VirtualHardware | A virtual gamepad and touch screen; files for battery and AC | Linux input events for the logical buttons, sticks and touch; the power supply files |
| Power | powerd | A process that sleeps, powers off and on the simulated console | Sleep on a short POWER press, shutdown on a long one |
| Clock and zone | timectl | A fake clock: host time plus an offset; the host's clock is never touched | The system clock: one-shot NTP, /etc/localtime, hardware clock |
| Network | netctl | The host's network, with made-up Wi-Fi networks to connect to | Wi-Fi control on the device's interface |
| Audio | ALSA configuration | The host's sound server | ALSA directly |
| Vibration | sysapi | Logged, with the page's edge lighting up | Strength written to the motor's file |
| Display | A Weston output, 640×480 | A window, or a stream in a browser | A DRM/KMS panel |
| External display | extdisplay (rules) and a driver | A second virtual screen, plugged and unplugged by a call | Connector hot-plug and mode, and a pointer of its own |
| Storage | The memory card's mount | A sparse ext4 image | The card |
| Swap | memd | zram plus a backing file | zram with write-back to flash |
| Temp-directory pressure | tmpwatch | Watches the host's RAM-backed /tmp | The same, if /tmp is in RAM |
Required of any Linux target
- Weston 14.x, WPE WebKit 2.52.x (libwpe, wpebackend-fdo, cog), Python 3 for the daemon, and GStreamer with H.264/AAC and VP8/Opus decoding for media.
- A 640×480 display, a gamepad-style input set and touch. The interface is designed for them (see the input model).
- About 2 GB of RAM for everything open.
- Ports: shell 8765, power 8764, Caroline 48765–48767, A2A 48772, store apps 49000–49999, inspector 9222. Each simulator instance adds 100 per instance number.
Memory that holds
Everything Beroun runs lives inside one memory budget. On top of it sit compressed swap in RAM and write-back of idle pages to flash under a daily write limit. When room still runs out, the service manager stops the lowest-priority services first.
The simulator target
The simulator runs the same stack natively and shows it in one window, or streams it to a browser. No CPU or GPU is emulated: only the interface above is replaced. That is why the manifests, the shell, the apps and Caroline are exactly the ones a device runs. Development never waits for hardware.
- A virtual gamepad, touch screen, battery and memory card.
- The memory budget and swap enforced on the PC.
- A second screen on demand for external-display apps.
- Several simulators side by side, each with its own ports, data and card.
Beroun on Android
The design: Beroun runs as an ordinary Android app, and every app, the same packages as in the store and never rebuilt, runs in it on a phone or a tablet. Interfaces are HTML, JavaScript and CSS, so the app is a shell around a web view.
| Question | Decision |
|---|---|
| Web engine | The system WebView (Chromium). The shell checks its version at start and asks for an update below a minimum |
| Screen | None of its own: immersive full screen, the WebView is the whole screen |
| Controls | An Android input method of our own, in the same APK, that repeats the logical buttons. Text uses Android's keyboard |
| Pages | Served by WebViewAssetLoader with the same paths: /apps/<id>/…, /system/<id>/…, /api/… |
| Browser | In WebViews of the shell |
| Wi-Fi, date and time | Android versions of these apps, managing Android's own settings |
| New API | Platform.capabilities() and Platform.device(), so an app knows where it runs |
The Python side (services, MCP servers, the shell and Caroline) runs inside the APK on CPython, with the shell in an Android mode. Caroline's updates for platform beroun run unchanged.
Adding a target interface
Add the method to VirtualHardware (or the matching module), expose it in the shell, document the counterpart in the table above, and add a Caroline tool for any new /api/ route.
