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. |
||
|---|---|---|
| .. | ||
| overlay | ||
| patches | ||
| tests | ||
| apply.sh | ||
| README.md | ||
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 underhttp/,queue/,command/,util/. Each file's header says what it does.DualLegCapturerecords the two call legs as separate channels; the alignment logic it depends on lives inutil/LegInterleaverso 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), forceVOICE_CALLcapture (0003), pre-grantRECORD_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.