Spec for full AI agent mobile control capability:
- Voice call control (dial/answer/hangup/status/list)
- App lifecycle management (install --url, update, permissions, grant, info)
- Device backup & restore (create/list/restore/app/verify, AES-256 encrypt)
- SMS send/delete + wait-reply via KDE Connect
- Audio control (volume/mute/route)
- Contacts management (list/add/export VCF)
56 tasks across 7 phases. TDD: fixtures → RED tests → GREEN impl.
Target: ≥130 BATS tests on completion.
Closes: specs/003-autonomous-agent-control/{spec,plan,tasks}.md
203 lines
7.1 KiB
Markdown
203 lines
7.1 KiB
Markdown
# Implementation Plan: Autonomous AI Agent Mobile Control
|
|
|
|
**Feature**: 003-autonomous-agent-control
|
|
**Created**: 2026-03-02
|
|
**Status**: Draft
|
|
**Spec**: `specs/003-autonomous-agent-control/spec.md`
|
|
|
|
---
|
|
|
|
## Technical Context
|
|
|
|
| Component | Technology | Rationale |
|
|
|-----------|-----------|-----------|
|
|
| Call control | `adb shell am start -a android.intent.action.CALL` + UIAutomator | ADB intent for dial; UIAutomator for answer/hangup (no root needed) |
|
|
| Call state | `adb shell dumpsys telephony.registry` | Exposes call state without root |
|
|
| App install (URL) | `curl` download → `adb install` | Reuses existing `adb install` path |
|
|
| App update | `adb install -r` (replace) | Standard ADB replace-install |
|
|
| App permissions | `adb shell dumpsys package <pkg>` | Full permission dump |
|
|
| App grant | `adb shell pm grant <pkg> <perm>` | Runtime permission grant |
|
|
| Backup | `adb backup -apk -shared -all` + `adb pull` for SMS/contacts | Android 9 supports `adb backup` |
|
|
| SMS send | `kdeconnect-cli --send-sms` | Already paired, used in existing sms commands |
|
|
| SMS wait-reply | Poll `kdeconnect-cli --list-notifications` with timeout | KDE Connect exposes incoming SMS as notifications |
|
|
| Audio control | `adb shell media volume` + `adb shell service call audio` | Media volume API |
|
|
| Contacts | `adb shell content query --uri content://contacts/phones` | Content provider query |
|
|
|
|
---
|
|
|
|
## Constitution Check
|
|
|
|
- [x] **Library-First**: New commands added to `lib/call.sh`, `lib/backup.sh`, `lib/contacts.sh`
|
|
- [x] **CLI Interface**: All new commands exposed via `fs5` entrypoint with `--help`
|
|
- [x] **Test-First**: BATS tests written before implementation (RED → GREEN)
|
|
- [x] **Simplicity**: Extends existing `fs5` CLI — no new entrypoints
|
|
- [x] **Anti-Abstraction**: Direct ADB/KDE Connect calls, no wrapper frameworks
|
|
- [x] **Integration-First**: Tests run against real device where possible; fixtures for offline
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### New Library Modules
|
|
|
|
```text
|
|
lib/
|
|
├── adb.sh (existing — adb_check_device, adb_cmd, etc.)
|
|
├── output.sh (existing — out_human, out_json, out_error)
|
|
├── input.sh (existing — tap, swipe, key, type)
|
|
├── call.sh (NEW — call_dial, call_answer, call_hangup, call_status, call_list)
|
|
├── backup.sh (NEW — backup_create, backup_list, backup_restore, backup_app, backup_verify)
|
|
└── contacts.sh (NEW — contacts_list, contacts_add, contacts_export)
|
|
```
|
|
|
|
### fs5 Entrypoint Extensions
|
|
|
|
New subcommands added to `fs5`:
|
|
|
|
| Subcommand | Library | P1/P2/P3 |
|
|
|------------|---------|----------|
|
|
| `call dial/answer/hangup/status/list` | `lib/call.sh` | P1 |
|
|
| `app install --url` | `lib/adb.sh` (extend) | P1 |
|
|
| `app update [--all]` | `lib/adb.sh` (extend) | P1 |
|
|
| `app permissions/grant/info` | `lib/adb.sh` (extend) | P1 |
|
|
| `backup create/list/restore/app/verify` | `lib/backup.sh` | P1 |
|
|
| `sms send [--wait-reply]` | `lib/adb.sh` (extend) | P2 |
|
|
| `sms delete` | `lib/adb.sh` (extend) | P2 |
|
|
| `audio volume/mute/route` | `lib/call.sh` (extend) | P2 |
|
|
| `contacts list/add/export` | `lib/contacts.sh` | P3 |
|
|
|
|
---
|
|
|
|
## Data Model
|
|
|
|
### Call State JSON
|
|
|
|
```json
|
|
{
|
|
"state": "active",
|
|
"number": "+49123456789",
|
|
"direction": "outgoing",
|
|
"duration_seconds": 42,
|
|
"timestamp": "2026-03-02T18:30:00Z"
|
|
}
|
|
```
|
|
|
|
### Backup Manifest JSON
|
|
|
|
```json
|
|
{
|
|
"id": "backup-20260302-183000",
|
|
"timestamp": "2026-03-02T18:30:00Z",
|
|
"path": "/backups/backup-20260302-183000.tar.gz",
|
|
"size_bytes": 524288000,
|
|
"checksum": "sha256:abc123...",
|
|
"contents": ["apks", "appdata", "sms", "contacts", "calllog"],
|
|
"device_serial": "RD51QE202392",
|
|
"android_version": "9"
|
|
}
|
|
```
|
|
|
|
### AppInfo JSON
|
|
|
|
```json
|
|
{
|
|
"package": "com.example.app",
|
|
"version_name": "1.2.3",
|
|
"version_code": 123,
|
|
"install_date": "2026-01-15T10:00:00Z",
|
|
"size_bytes": 10485760,
|
|
"is_system": false,
|
|
"permissions": {
|
|
"granted": ["android.permission.CAMERA"],
|
|
"denied": ["android.permission.READ_CONTACTS"]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Key Technical Decisions
|
|
|
|
### ADR-001: Call Control via ADB Intent + UIAutomator
|
|
|
|
**Decision**: Use `adb shell am start -a android.intent.action.CALL tel:<number>` for
|
|
dialing. Use UIAutomator to tap answer/hangup buttons (no root required on Android 9).
|
|
|
|
**Alternative rejected**: `adb shell service call phone` — requires root on Android 9.
|
|
|
|
**Consequence**: `call answer` requires UIAutomator XML dump to find button coordinates.
|
|
Add fixture for offline testing.
|
|
|
|
### ADR-002: Backup via `adb backup` + Content Providers
|
|
|
|
**Decision**: Use `adb backup -apk -shared -all -f backup.ab` for app data.
|
|
Use content provider queries for SMS (`content://sms`) and contacts (`content://contacts`).
|
|
|
|
**Alternative rejected**: Third-party backup apps — requires installation and UI automation.
|
|
|
|
**Consequence**: `adb backup` is deprecated in Android 12+ but fully functional on
|
|
Android 9 (FS5 target). Document this limitation.
|
|
|
|
### ADR-003: SMS Send via KDE Connect
|
|
|
|
**Decision**: Use `kdeconnect-cli --send-sms "<msg>" --destination <number> -d <device-id>`
|
|
|
|
**Alternative rejected**: `adb shell service call isms` — requires root.
|
|
|
|
**Consequence**: KDE Connect must remain paired. Add pairing check to `sms send`.
|
|
|
|
---
|
|
|
|
## Test Strategy
|
|
|
|
### Offline Tests (no device required)
|
|
|
|
- `backup verify` — checksum validation against fixture
|
|
- `backup list` — parse fixture backup directory
|
|
- `app info` — parse fixture `dumpsys package` output
|
|
- `call status` — parse fixture `dumpsys telephony.registry` output
|
|
- `contacts list` — parse fixture content provider output
|
|
|
|
### Online Tests (device required, marked `@requires_device`)
|
|
|
|
- `call dial` — initiates call (verify via `call status`)
|
|
- `backup create` — creates archive (verify size > 0)
|
|
- `app install --url` — downloads and installs test APK
|
|
- `sms send` — sends SMS (verify via `sms list`)
|
|
|
|
### Fixture Files
|
|
|
|
```text
|
|
tests/fixtures/
|
|
├── ui_dump.xml (existing)
|
|
├── dumpsys_telephony.txt (NEW — call state output)
|
|
├── dumpsys_package.txt (NEW — app info output)
|
|
├── content_sms.txt (NEW — SMS content provider output)
|
|
└── content_contacts.txt (NEW — contacts content provider output)
|
|
```
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
| Dependency | Status | Notes |
|
|
|------------|--------|-------|
|
|
| `adb` | ✅ Available | Used throughout existing commands |
|
|
| `kdeconnect-cli` | ✅ Paired | Used in existing `sms` commands |
|
|
| `curl` | ✅ Available | For APK URL download |
|
|
| `sha256sum` | ✅ Available | For backup verification |
|
|
| `openssl` | ✅ Available | For AES-256 backup encryption |
|
|
| `bats` 1.13.0 | ✅ Available | Test runner |
|
|
| UIAutomator | ✅ Available | Used in existing `ui` commands |
|
|
|
|
---
|
|
|
|
## Risks
|
|
|
|
| Risk | Likelihood | Mitigation |
|
|
|------|-----------|------------|
|
|
| `adb backup` blocked by device policy | Low | Android 9 allows it; document if blocked |
|
|
| Call answer via UIAutomator fails (button layout changes) | Medium | Use multiple selector strategies (text + content-desc) |
|
|
| KDE Connect pairing lost | Low | Add `sms send` pairing check with re-pair instructions |
|
|
| APK URL download fails (network) | Medium | Retry logic + clear error message |
|