Skip to content

feat: ai.poly:voice — WebRTC voice calling SDK#8

Merged
Zakariya1057 merged 1 commit into
mainfrom
mes-185-webrtc-android
Jul 1, 2026
Merged

feat: ai.poly:voice — WebRTC voice calling SDK#8
Zakariya1057 merged 1 commit into
mainfrom
mes-185-webrtc-android

Conversation

@Zakariya1057

@Zakariya1057 Zakariya1057 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Overview

Adds ai.poly:voice (the :polyvoice module) — live two-way WebRTC voice calls to a PolyAI
agent, the on-device counterpart to ai.poly:messaging. Ships as a separate artifact so chat-only apps
stay lean (the call path pulls in the native libwebrtc audio engine).

This also bumps the SDK to 0.9.0 — tagging v0.9.0 after merge publishes ai.poly:messaging:0.9.0
and the first-ever ai.poly:voice:0.9.0.

What's new

:polyvoice module — hexagonal ports/adapters (mirrors :polymessaging):

  • A pure CallCoordinator state machine (auth → session → link → ICE → signaling → peer → offer),
    signaling wire codec, trickle-ICE buffering (both directions), connection-timeout + disconnect-grace,
    signaling-drop reconnect with backoff (1s/2s/4s ×3), idempotent teardown.
  • libwebrtc peer (Unified Plan, deadlock-safe native teardown) + OkHttp REST/WS adapters.
  • Audio output — accessory-aware by default: the call follows a connected wired/Bluetooth headset
    automatically
    and auto-switches when you plug/unplug one mid-call, falling back to speaker (or
    earpiece). A picker (call.audio + setAudioDevice) lets users pin any output and return to
    automatic via setAudioDevice(null) — API 31+ communication-device model + the legacy SCO path, with
    live change events. All route mutation is serialized under a lock against the coordinator thread.
  • Audio-focus interruptions: transient loss → mute/restore (call stays connected); permanent loss /
    incoming phone call → end with PolyError.Voice.Interrupted.
  • Credentials: Configuration.apiKey (X-Token) + a required, distinct VoiceOptions.webrtcToken
    (the gateway auth token). Session create reports platform=android + a detected device_type
    (mobile/tablet), consistent with ai.poly:messaging.
  • Public API mirrors :polymessaging idioms — Kotlin suspend and Java Callback/Executor
    overloads on everything. Ships consumer R8 keep rules for the JNI surface.

:polymessaging — additive only: PolyError.Voice.Disconnected + Interrupted; PolyCall KDoc
now points at the voice artifact. ABI otherwise unchanged.

Examples reorganized into examples/chat/{compose,views} and examples/voice/{compose,views} — a
tap-to-call demo with the audio-output picker (incl. an Auto option) and a microphone foreground
service
(+ wake lock) so calls survive backgrounding.

Docs — a dedicated polyvoice/README.md guide (permissions, credentials,
audio output, interruptions, backgrounding, R8); the root README keeps a concise voice quickstart that
links to it.

Testing

  • JVM unit tests in :polyvoice over port fakes (signaling codec, the full coordinator state
    machine, ICE buffering, timeouts, disconnect-grace + reconnect, mute, audio-device selection, focus
    interruptions, platform/device_type on session create) + the :polymessaging suite; both
    apiChecks green. CI runs build test lint apiCheck.
  • On-device: two-way audio, accessory-aware routing + mid-call switching (speaker / earpiece /
    Bluetooth), incoming-call interruption (ends with Interrupted), and backgrounded-call survival
    (foreground service + wake lock) all verified.
  • The accessory-aware routing was reviewed for cross-thread safety — all route mutation is serialized
    under a lock.

Notes

  • The voice examples use YOUR_API_KEY / YOUR_WEBRTC_TOKEN placeholders (set them in the
    PolyVoice.call(...) block) — no committed credentials.
  • The chat examples move (examples/compose|viewsexamples/chat/...) shows as git renames — most of
    the file count is moves; the substantive surface is polyvoice/ + examples/voice/.

@Zakariya1057
Zakariya1057 force-pushed the mes-185-webrtc-android branch 6 times, most recently from 45851a5 to a9b59f1 Compare June 30, 2026 15:25
@Zakariya1057 Zakariya1057 changed the title feat: ai.poly:voice — WebRTC voice calling SDK (MES-185) feat: ai.poly:voice — WebRTC voice calling SDK Jun 30, 2026
@Zakariya1057
Zakariya1057 force-pushed the mes-185-webrtc-android branch 2 times, most recently from 34c10af to d5aeb9b Compare June 30, 2026 16:42
New :polyvoice module (ai.poly:voice) — live two-way WebRTC voice calls to a
PolyAI agent, alongside ai.poly:messaging. Bumps the SDK to 0.9.0 (first
ai.poly:voice publish, with ai.poly:messaging:0.9.0).

- Hexagonal ports/adapters over libwebrtc + OkHttp; a pure CallCoordinator
  state machine (auth → session → link → ICE → signaling → peer → offer),
  signaling wire codec, trickle-ICE buffering, connection-timeout +
  disconnect-grace, signaling-drop reconnect with backoff, idempotent teardown.
- Audio: MODE_IN_COMMUNICATION + focus. Output routing is accessory-aware by
  default — follows a connected wired/Bluetooth headset, auto-switches on
  plug/unplug, falls back to speaker/earpiece; a picker (call.audio +
  setAudioDevice) pins any output or returns to automatic. API 31+
  communication-device model + the legacy SCO path; route mutation serialized
  under a lock. Audio-focus interruptions: transient → mute/restore,
  permanent / incoming call → end with PolyError.Voice.Interrupted.
- Credentials: Configuration.apiKey (X-Token) + a required, distinct
  VoiceOptions.webrtcToken. Session create reports platform + a detected
  device_type (mobile/tablet), consistent with ai.poly:messaging.
- Public API mirrors :polymessaging idioms (Kotlin suspend + Java
  Callback/Executor overloads); ships consumer R8 keep rules. JVM tests over
  port fakes.

polymessaging: additive PolyError.Voice.Disconnected + Interrupted; PolyCall
KDoc points to the voice artifact (no other ABI change).

Examples reorganized into examples/chat/{compose,views} and
examples/voice/{compose,views} — a tap-to-call demo with the audio-output
picker (incl. an Auto option) and a microphone foreground service (+ wake
lock) so calls survive backgrounding.

Docs: a dedicated polyvoice/README.md voice guide (permissions, credentials,
audio output, interruptions, backgrounding, R8); the root README keeps a
concise voice quickstart that links to it.
@Zakariya1057
Zakariya1057 force-pushed the mes-185-webrtc-android branch from d5aeb9b to 02e15ab Compare June 30, 2026 16:50
@Zakariya1057
Zakariya1057 merged commit 1a250fc into main Jul 1, 2026
3 checks passed
@Zakariya1057
Zakariya1057 deleted the mes-185-webrtc-android branch July 1, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant