This project is the Android sibling of the Linux `hermes-node-agent`. The goal is **functional parity where Android permits it**, not a toy “status-only” agent.
This project is the Android sibling of the Linux `hermes-node-agent`. It reuses existing Hermes Node Gateway capability names where Android can provide equivalent intent, instead of inventing a separate `phone_control` gateway tool.
The gateway should not need a new “phone_control” tool just because the node is Android. Where the existing capability names already describe the intent, Android should reuse them and implement Android-native semantics behind the same wire contract.
Remote:
## Current status
Early Android/Kotlin scaffold with protocol/capability classes. The project already has a GitLab remote:
```text
```text
git@git.nexlab.net:lisa/hermes-node-android.git
git@git.nexlab.net:lisa/hermes-node-android.git
```
```
## Current status
Buildable first test APK.
Implemented enough to install on a phone and connect it to the Hermes Node Gateway:
- Android/Kotlin app project with Gradle wrapper.
- Config UI for gateway URL, token, node name, TLS mode, and advertised capabilities.
- Foreground service for persistent outbound WebSocket connection.
- Registration frame compatible with Hermes Node Gateway-style capability discovery.
- Reconnect loop and heartbeat frames.
- App-local config via `SharedPreferences`; no hardcoded token.
- Status display in the app.
- Debug APK build verified locally.
Baseline capability handlers:
-`computer_control`
-`launch_app`: implemented via package launch intent.
-`open_url`: implemented via `ACTION_VIEW`.
-`open_intent`: implemented for implicit Android intents.
- gesture/key/text actions return explicit unsupported until AccessibilityService backend is added.
- On Android: media session controls, volume, audio route/status, playback of provided audio, mic capture only with permission and visible UX.
-`camera_control` = camera read paths where supported.
-`camera_control` = camera read/write paths where supported.
-`browser_control` = reserved for a future browser automation backend.
- On Android: list cameras, capture frame/video with CameraX/Camera2 and explicit permission/visible UX. Virtual camera injection is not an Android baseline feature.
-`exec` = Android shell execution if ever explicitly designed; disabled by default.
-`browser_control` = browser automation if implemented later via Chrome DevTools/WebView/intent flows. For first pass, browser launching/open URL can live under `computer_control` actions.
-`exec` = Android shell execution if available, disabled by default and honest about non-root limitations.
This avoids gateway-side churn while still letting the gateway inspect `capability_info.platform == "android"` when it needs platform-specific hints.
## Design goals
-**Protocol-compatible** with existing Hermes Node Gateway JSON/WebSocket protocol.
-**Outbound-only** connection from Android to gateway: `wss://gateway:8765`.
-**Functional parity with Linux capabilities where Android permits it.**
-**No root requirement** for baseline operation.
-**Foreground service** for persistent connectivity.
-**No hidden capture or spyware behavior.** If Android requires a visible permission prompt or foreground notification, we respect that.
-**No hardcoded tokens.** Config is app-local and user-supplied.
## First implementation targets
### `computer_control`
Android-native actions:
-`launch_app` by package name.
-`open_url` via browser intent.
-`open_intent` for explicit/implicit intents.
-`key_press` for Android navigation keys where permitted: Back, Home, Recents, Enter, Volume Up/Down.
-`type_text` through accessibility/IME path where available.
-`tap`, `swipe`, `long_press` through accessibility gesture dispatch where enabled.
-`get_active_window` mapped to foreground app/activity when available.
### `desktop_observe`
The gateway can inspect `capability_info.platform == "android"` and `platform_semantics == "android_phone_control"` for platform-specific hints while keeping the public tool names stable.
Android-native observations:
## Build
-`screen_info`: display size, density, orientation, interactive/locked state where available.
Prerequisites:
-`active_window`/`get_active_window`: foreground app/activity via usage stats or accessibility, depending on grants.
-`screenshot`: MediaProjection-based capture with explicit user consent.
-`clipboard_get`: only when Android version/API permits it for the foreground/default IME constraints.
### `audio_control`
- JDK 17
- Android SDK with platform 35 available
-`list_audio_devices`
Build debug APK:
-`get_audio_status`
-`play_audio`
-`capture_input` with runtime microphone permission and foreground UX
-`capture_output` only if Android API/app constraints allow; otherwise explicit unsupported result.
### `camera_control`
```bash
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \
ANDROID_HOME=/usr/lib/android-sdk \
ANDROID_SDK_ROOT=/usr/lib/android-sdk \
./gradlew --no-daemon assembleDebug
```
-`list_cameras`
Output:
-`get_camera_status`
-`capture_frame`
-`capture_video`
-`inject_video`: return explicit unsupported on normal Android unless a later rooted/vendor-specific backend exists.
### `exec`
```text
app/build/outputs/apk/debug/app-debug.apk
```
- Optional Android shell command execution using app-accessible process execution.
## Install/test on Android phone
- Disabled by default.
- Must return honest permission/SELinux/root limitations.