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
7.1 KiB
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
- Library-First: New commands added to
lib/call.sh,lib/backup.sh,lib/contacts.sh - CLI Interface: All new commands exposed via
fs5entrypoint with--help - Test-First: BATS tests written before implementation (RED → GREEN)
- Simplicity: Extends existing
fs5CLI — no new entrypoints - Anti-Abstraction: Direct ADB/KDE Connect calls, no wrapper frameworks
- Integration-First: Tests run against real device where possible; fixtures for offline
Architecture
New Library Modules
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
{
"state": "active",
"number": "+49123456789",
"direction": "outgoing",
"duration_seconds": 42,
"timestamp": "2026-03-02T18:30:00Z"
}
Backup Manifest 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
{
"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 fixturebackup list— parse fixture backup directoryapp info— parse fixturedumpsys packageoutputcall status— parse fixturedumpsys telephony.registryoutputcontacts list— parse fixture content provider output
Online Tests (device required, marked @requires_device)
call dial— initiates call (verify viacall status)backup create— creates archive (verify size > 0)app install --url— downloads and installs test APKsms send— sends SMS (verify viasms list)
Fixture Files
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 |