Prd/components/dialer-patch
Lucy Doupalů be9f14ce34 Helpdesk - operator console + patched GrapheneOS Dialer for call handling
A small helpdesk system: an office Pixel running a patched GrapheneOS Dialer
answers technician calls, records both call legs as separate channels, and a
Ruby backend transcribes them through Whisper and files an AI summary against
the caller.

Squashed to a single commit for sharing. No credentials are included; secrets
live outside the repo in /etc/helpdesk/env on the server or a gitignored
.claude/env.local locally. See .claude/env.local.example for the shape.

Start at README.md, then docs/architecture.md.
2026-07-27 18:50:32 +02:00
..
overlay Helpdesk - operator console + patched GrapheneOS Dialer for call handling 2026-07-27 18:50:32 +02:00
patches Helpdesk - operator console + patched GrapheneOS Dialer for call handling 2026-07-27 18:50:32 +02:00
tests Helpdesk - operator console + patched GrapheneOS Dialer for call handling 2026-07-27 18:50:32 +02:00
apply.sh Helpdesk - operator console + patched GrapheneOS Dialer for call handling 2026-07-27 18:50:32 +02:00
README.md Helpdesk - operator console + patched GrapheneOS Dialer for call handling 2026-07-27 18:50:32 +02:00

components/dialer-patch

The GrapheneOS Dialer patch: auto-record on answer, call webhooks to the backend, recording upload, and the reverse command channel (answer/mute/hold/dial from the console). It runs as a privileged system app inside a self-built OS image - a normal app can't capture call audio - so this directory holds only our sources, and the huge upstream Dialer tree is fetched separately (resources/scripts/, git-ignored).

Base: the in-tree callrecV2 recording implementation (Dialer commit 6f68bcbd).

Layout

  • overlay/java/com/android/dialer/helpdesk/ - all new code, one package. Entry points: CallEventEmitter (webhooks), HelpdeskRecordingBridge (upload), HelpdeskCommandService + CommandChannelClient (the always-on reverse channel), HelpdeskConfig (URL + credentials), HelpdeskHeartbeat, ContactsSyncer, and the pure-logic helpers under http/, queue/, command/, util/. Each file's header says what it does. DualLegCapture records the two call legs as separate channels; the alignment logic it depends on lives in util/LegInterleaver so it can be tested off-device.
  • patches/0001-0011 - the changes to AOSP files, one concern per patch: register the emitter (0001), recording auto-start and hold behaviour (0002, 0007), force VOICE_CALL capture (0003), pre-grant RECORD_AUDIO (0004), foreground-service manifest bits (0005), allow cleartext for dev LAN backends (0006), landscape in-call UI (0008), keep our notification channel alive (0009), runtime-selectable recording quality plus a per-speaker capture probe (0010), recording the two call legs as separate channels (0011).
  • overlay/etc/default-permissions/ - the pre-grant XML.
  • tests/ - off-device tests, see below.
  • apply.sh - copies the overlay and applies all patches into a Dialer tree (DIALER_TREE, defaults to the build box's /build/grapheneos/...). Idempotent; safe to re-run.

The companion components/sepolicy-patch is required in the same image - without its property context the Dialer can't read the persist.helpdesk.* configuration at all.

Build and flash

docs/runbooks/graphene-build.md (Linux) and docs/runbooks/windows-wsl2-build.md. How the device finds and authenticates to the backend, including every config property and a troubleshooting table: docs/phone-connectivity.md. The wire contract: docs/device-api.md.

Tests

tests/run.sh           # compiles the pure-logic classes and cross-checks them against the Ruby backend
tests/integration.sh   # signed HTTP against a real local backend (starts one on :4055)

Both need a JDK (the GrapheneOS prebuilt at /build/grapheneos/prebuilts/jdk/... or a system javac) and Ruby. The cross-checks matter because several classes mirror backend logic byte-for-byte: E.164 normalization, business hours, the HMAC recipe, the command-verb set.