FaB Calls

A voice-calling proof of concept. Two Android phones, one call, and a lot of measurement. This page installs it and explains every control.

Download FaB Calls Android 12 or newer  •  71 MB  •  version 0.1-poc  •  build 68

Read this first. This is not a Play Store app. Android will warn you before installing it, and it is right to. Install it only because someone you trust sent you the link.

Installing it

  1. Tap the download button above. Chrome will ask whether to keep the file; choose to keep it. It may say the file type can harm your device - that warning appears for every APK, signed or not.
  2. Open the downloaded file. From the download notification, which is the reliable route. If you go via Files, then Downloads instead, note that every download is saved as fab-calls.apk, so a second one becomes fab-calls (1).apk and a third fab-calls (2).apk. Opening the wrong one installs an older build and looks exactly like the update having failed. Delete the old ones before you download, or use the notification.
  3. Allow installs from this source. The first time, Android says something like "For your security, your phone is not allowed to install unknown apps from this source." Tap Settings, turn on Allow from this source, then press back. You are allowing Chrome (or Files) to install apps, not granting anything to this app.
  4. Install. Play Protect may offer to scan it - let it, or tap Install anyway. It has never seen this app before, which is all its warning means.
  5. Open the app and allow the microphone. It asks once. Decline it and the app will tell you it cannot make calls, because it cannot.

Checking you got the right file

Optional, and only if you like that sort of thing. The SHA-256 of the APK this page serves is also published at fab-calls.apk.sha256:

db1a1033c149eae7a6fcfbf52ec80350275269c50462d96b1df6a47bfe13557f

Two things to know before you try a call

Both phones need the app open on screen. There are no push notifications yet - it was left out of the proof of concept on purpose. So the app can only receive a call while it is running with a live connection. Lock the phone and put it in your pocket and it will go quiet within a minute or two, and calls to it will fail. That is expected, not a fault.

Android 12 or newer. The app uses the modern audio-routing API and there is deliberately no fallback for older versions.

Making a call

  1. Both phones open the app. The top line should say Signalling: registered.
  2. Each phone shows You are: peer-xxxxxx. Send yours to the other person - text, WhatsApp, read it out, whatever.
  3. One phone types the other's peer-xxxxxx into Peer identity and taps Call.
  4. The other phone rings and vibrates, and shows Answer and Reject.
  5. Talk. Hang up ends it from either side.

Every control on the screen

The top of the screen

What it saysWhat it means
Signalling: registeredConnected to the server and reachable. Calls can arrive.
Signalling: connectingTrying. It retries on its own, backing off to every 30 seconds, so leaving it alone is usually right.
You are: peer-xxxxxxYour address. Derived from the phone, so it stays the same until the app is reinstalled.
Server: wss://...The signalling server. Already correct - Change exists for testing against a different one, and getting it wrong makes the app unreachable.
Relay: readyA TURN relay is available, so a call can connect even when the two phones have no direct route to each other. Worth glancing at before blaming a failed call on the far end.
Relay: noneNo relay. Calls still work if both phones can reach each other directly, which on the same wifi they usually can.

During a call

ControlWhat it does
Hang upEnds the call for both sides.
MuteStops sending your audio. You still hear them.
Earpiece / Speaker / Bluetooth / WiredWhere the call's audio goes. Only routes the phone actually has are offered. Bluetooth appears when a headset is already connected.

Mouth-to-ear latency

The reason this app exists. It measures how long your voice actually takes to reach the other person's ear: not the network round trip, but the whole path, including both phones' audio hardware.

ControlWhat it does
CalibrateDo this first, on each phone. Plays a short tone out of the loudspeaker and listens for it, measuring that phone's own speaker-to- microphone loop. Takes about a second and needs no call. You will hear a brief beep. It reports something like "This phone's loop: 211.5 ms".
MeasureNeeds a live call and a calibration on both phones. Bounces tones between the handsets, subtracts both loops, and halves the remainder. Reports a mouth-to-ear figure with a confidence.
Measurement modeTurns off echo cancellation so the test tone survives the trip. It applies to the next call, and while it is on the audio is not what a normal call sounds like - so leave it off unless you are measuring.

Quiet room, phones a few centimetres apart. The measurement listens for a tone through the air, so a noisy room or a hand over the speaker will make it fail. If calibration says it heard nothing, that is usually why.

The Engineering panel

Live numbers, updated during a call. Everything reads not measured until there is a call to measure.

RowWhat it is
mouth-to-ear delayThe headline figure, once you have run Measure. Under about 150 ms feels like a normal phone call; past 300 ms people start talking over each other.
round-trip timeNetwork only, reported by WebRTC. Always lower than mouth-to-ear, because it excludes both phones' audio hardware.
packet lossShare of audio packets that never arrived. Anything above a few per cent is audible as clipping.
RTP jitterHow unevenly packets arrive. High jitter sounds robotic even when nothing is lost.
jitter-buffer delayDelay deliberately added at the receiving end to smooth jitter out. It is part of why mouth-to-ear exceeds round-trip.
Opus payload bitrateHow much audio data is actually flowing. Drops sharply when nobody is talking, which is Opus working correctly rather than a fault - see the note below about degraded.
call setupFrom pressing Call to audio flowing.
codecShould say opus. Anything else is a bug.
ICE routeHow the audio is travelling: host (same network), srflx (direct through NAT), or relay (via the TURN server). Relay costs bandwidth and adds delay, so it is worth knowing.
loss 10 s / 30 sRecent loss over short windows, which catches a bad patch that a whole-call average would flatten out.
concealmentHow much audio the decoder had to invent to cover missing packets. The number that best matches "it sounded rough".

If it does not work

SymptomLikely cause
Signalling: connecting, and it stays thereNo internet, or the server is being redeployed. It retries by itself; give it a minute.
Call fails immediatelyThe other phone is not registered - app closed, screen off, or its connection has dropped.
Rings, answers, then silenceNo media path. Check Relay on both phones, and ICE route in Engineering.
Nothing happens when a call arrivesThe phone is on silent. It still vibrates unless silent mode is fully on.
Calibration heard nothingToo noisy, speaker covered, or the volume is right down. Turn the volume up and try in a quiet room.
It says Overall: degraded but the call sounds fineUsually the Opus bitrate while neither of you is speaking - the codec drops its rate on silence, and the summary takes that at face value. Talk for a few seconds and look again. Judge it on packet loss, jitter and concealment, which describe what you can actually hear.