How JemRec works
Android’s voice-call audio source carries both sides of a
call, and reading it needs permissions no ordinary app can hold — but
the shell user, the one an ADB session runs as, holds them. Getting shell
privilege normally means a computer, or root, or a second app you keep
alive. JemRec needs none of them, because the phone can be its own
computer.
- The app pairs with the phone’s own Wireless debugging — the same pairing a laptop does, with both ends on the same handset.
- For a few seconds, it uses that session to start a small recorder that runs as the shell, then closes it. The recorder outlives the session.
- The recorder watches the calls and writes each one to a file itself, so a phone that freezes background apps cannot cut a recording short.
- The app collects the finished file over a socket on which the recorder and the app each prove who they are.
The whole design, with the measurement behind each decision, is in ARCHITECTURE.md.
The design
The phone is both ADB host and ADB device
The app embeds an ADB client and pairs, over 127.0.0.1, with
the phone’s own Wireless debugging — the same six-digit pairing a
laptop does, with both ends on the same handset. Nothing leaves the phone.
ADB is a bootstrap, not a transport
That session lasts seconds. In it the app grants itself one settings permission and launches a small daemon from a jar it carries inside the APK, then closes the session. A process started from an ADB shell outlives the connection, which is the whole trick: with Wi-Fi off there is no ADB at all, so anything that needed it when a call arrived would simply not record.
The daemon records; the app collects
The daemon watches the call state and writes the call to a file. The app is never on the audio path. That split was forced by measurement: when the app handled live audio, the phone’s process manager froze it while the dialer was in front and a 76.7-second call arrived as 14 to 44 seconds. Afterwards the app fetches the finished file at whatever pace the system allows, and a freeze there costs a slower copy rather than a lost second.
Why the recorder writes the file, not the app
The socket is authenticated both ways
The daemon listens on loopback, which every process on the phone shares, so each connection proves itself with an HMAC exchange over a token that never crosses the socket. The daemon proves itself first — anything can bind that port while the daemon is down, and a scheme that sent the token as a password would hand it over.
It keeps itself alive
Losing Wi-Fi restarts the ADB daemon and kills what it spawned, so the recorder keeps one debugging switch on to survive it, and minds that switch itself. That is what lets a call be recorded in a field with no network. Some phones switch it off themselves — an Honor’s Settings app does each time Developer options opens — and the app is woken the moment that happens, to switch it back on.
A reboot is one thing it cannot survive, because starting the recorder is the single operation that needs ADB. A scheduled job and a system-held Wi-Fi watcher rebuild it without you within seconds of the phone joining a network — when the phone lets the app start in the background at boot to arm them. Where it does not, nothing is armed and nothing begins, which is why the manual says to open the app once after a restart. Either way the app says plainly that it cannot record rather than looking healthy, and after two minutes a notification says it too.
Unplugging the phone from a computer is the other. Measured on an Honor: three seconds after the cable came out, the phone stopped the ADB daemon, the recorder went with it, and nothing started the ADB daemon again. So the recorder watches the USB port and spends those three seconds waking the app, which switches Wireless debugging off and on — what has Android start the ADB daemon — and starts the recorder: recording again 12 to 16 seconds after the cable came out, nothing tapped. With the screen off that needs the app allowed to start by itself: left to the phone, an Honor froze it until it was woken — about four minutes, once 8.5 — and JemRec says so the moment it may run again, with a button to the setting. A charger stops nothing.
Unplugged from a computer, back by itself
Some phones also stop apps in the background to save power, and a stopped JemRec cannot start the recorder again once it goes. JemRec cannot change that setting, so setup asks you to, on the phone’s own screen for it; if the phone stops JemRec anyway — while it was working, or leaving it stopped — a notification says so. Android’s routine clean-up of an idle app is not counted: on an Honor, 2,015 of 2,062 such records were that, and none had left the app stopped.
What it does
WhatsApp, Telegram, Viber and Google Meet calls too
Messenger calls and Google Meet, both sides, each app switched on separately — and the caller’s name, if you let JemRec read the app’s call notification. Tested with WhatsApp, Telegram, Viber and Google Meet; Signal takes the same path and is not tested yet. Android allows this from version 14; on an older one, Settings says so.
An answering machine, if you want one
Off until you switch it on. It answers a call you have not taken, plays your own greeting with your microphone muted, and keeps the caller’s message. No app can play sound into a call, so the recorder does it, as the shell, through an output Android calls in-call music. Android’s own answer on whether a phone can do that was wrong on the Honor, so a test call, not a guess, says whether it works on yours.
It tells you when something is wrong
A recorder that fails quietly is found out on the day a call was needed. So after each call a silent notification shows the recording, with Play, Share and Delete; every recording is measured once it is saved, and one that came out silent is reported; a recorder that is down says why, with Pair again when the pairing is gone and Allow this Wi-Fi when Android has not allowed the network; and with call log access, an answered call that has no recording is reported once.
Every call, recorded or not
A Calls tab shows the phone's call log with a play mark on each recorded call, and, on one that was not recorded, why: recording was off, it was too short, it is in Recently deleted, or — in red — the answering machine could not take a message, or nothing explains it.
Cut to the call
A recording starts when the call is answered, not when you dial: no ringing at the start, and a call nobody picked up is not kept. With call waiting, each call gets a recording of its own. Android tells JemRec when each call is answered; tracking only listens. The one thing that ever answers a call is the answering machine, when you switch it on.
Exact call tracking keeps only the conversation
Only the calls you want
Keep every call, only your contacts’, only strangers’, or everyone’s but a few people’s. Name files by date, or with the caller or their number in them — and on an Honor, the way Honor’s own Phone app looks for them, so its call history gets a play button.
Nothing is deleted by accident
Delete moves a recording to Recently deleted, where it can be restored for 30 days, one by one or all at once, unless you empty it first. Auto-delete, off until you choose it, removes recordings past an age you pick and calls too short to have been a conversation, into the same place. A bookmark marks a recording to keep, and nothing removes a kept one. A Quick Settings tile turns recording on and off without opening the app, and a long press on it opens the app.
Off, and debugging with it, for banking apps
Some banking apps won’t open while Developer options or debugging is on. Turning JemRec off can hide Developer options and Wireless debugging too — the recorder keeps running on USB debugging, so it is back the moment JemRec is on — or switch all debugging off, the recorder with it, so that turning it on needs Wi-Fi. Turning it on puts back what it switched off. Settings → When JemRec is off.
Start without Wi-Fi, off until you switch it on, takes that Wi-Fi away until the phone restarts. Android allows Wireless debugging only on a Wi-Fi network the phone has joined, but adbd has another way in, its classic port, 5555, which listens with no network at all; JemRec asks adbd to open it, once each boot, over Wireless debugging. The cost is that the port is open on every network the phone joins whenever USB debugging is on — while JemRec is on, and while it is off unless all debugging goes with it — and announced there by the phone’s serial number: a computer that reaches it, or an app on the phone, cannot debug the phone without a yes on it, but it can ask.
What it asks for, and what it does not
No microphone permission. The app never records — the shell-side process does the capturing, your answering-machine greeting included — and a call recorder that asks for the microphone anyway is asking for something it does not use. Reading your call log and contacts is optional, offered once, and is used for two things only: labelling a recording with who the call was with, and noticing a call that went unrecorded. Knowing when a call is answered takes one more permission, one Android does not let apps ask for: JemRec’s recorder allows it, and turning off Exact call tracking in Settings takes it back.
Every permission, in the order F-Droid’s listing page shows them, because a permission a call recorder does not explain is one its user has to guess at:
| Permission | Why |
|---|---|
INTERNET | Not about the internet: Android requires it for any TCP socket, including one to 127.0.0.1. |
ACCESS_NETWORK_STATE | To tell whether there is Wi-Fi to rebuild the recorder over, instead of trying and failing. |
WRITE_SECURE_SETTINGS | Granted by the app to itself over its own ADB session. Nothing but a shell can grant it, so no user can be talked into it. It lets JemRec switch debugging back on when the phone turns it off, and off with JemRec when you ask it to. |
POST_NOTIFICATIONS | The recording notice, the ask-first prompt, the pairing code box. |
FOREGROUND_SERVICE, FOREGROUND_SERVICE_SPECIAL_USE | To stay alive while a call is being recorded and while the finished file is collected; while the recorder is restarted after a computer's cable comes out; and for the seconds it takes to warn that the phone stopped JemRec in the background. SPECIAL_USE is the honest type: the microphone type would need a microphone permission this app does not hold. |
RECEIVE_BOOT_COMPLETED | A reboot kills the recorder; this is what arms the job that rebuilds it. |
READ_MEDIA_AUDIO | To list recordings made before a reinstall. Refusing it only hides those. |
READ_EXTERNAL_STORAGE | Android 12 only, which has no READ_MEDIA_AUDIO: the same, to list recordings made before a reinstall. It covers photos and videos too; JemRec reads only its own folder. Refusing it only hides those. |
READ_CALL_LOG, READ_CONTACTS | Optional. The only way to know who a call was with: to label a recording, to name a file after the caller, to keep or leave out a call by who it was with, and, for the call log, to notice a call that went unrecorded. |
MANAGE_ONGOING_CALLS | For exact call tracking. Not one an app can ask for: the daemon allows it, as the shell, while the switch is on. Android then tells JemRec when each call is answered and ends. Tracking never acts on a call; the answering machine’s answering is the recorder’s, as the shell. |
USE_FULL_SCREEN_INTENT | Lets the ask-first prompt last a minute instead of five seconds. Not auto-granted, and nothing is gated on it. |
WAKE_LOCK | So the keep-alive job can finish its few seconds of work, and so a phone with its screen off stays awake while it brings the recorder back after a USB cable, a minute and a half at most. WorkManager declares it too. |
Recording calls is your responsibility. Consent law differs by country and sometimes by state: one party, all parties, or a spoken notice. This app records what you tell it to and warns nobody on your behalf.
Will it work on your phone?
One thing cannot be worked around: whether your phone’s audio hardware hands over the call at all. Some give both sides, some give one, some give silence. JemRec answers it in about a second — Settings, Diagnostics, Self-test — by opening a real capture down the same path a call takes and telling you what came out.
Both sides of the call have been recorded on five phones, across three very different Android builds: an Honor Magic 8 Pro on MagicOS 10, a Samsung Galaxy S20, a Galaxy S23 and a Galaxy M34 on One UI — the S23 and the M34 over Wi-Fi Calling too — and a OnePlus on LineageOS 23. Five is not a compatibility list, which is what the self-test is for.
OPPO, OnePlus and realme phones on their own systems (ColorOS, OxygenOS, realme UI) refuse JemRec the setting setup grants it until a switch of their own is set: Disable system optimization on, the last in Developer options’ Apps section (Disable permission monitoring on older ones, or Permission monitoring off). Setup names it before it is needed, and again if the phone refuses.