Not possible without root but even with root SoX recording might not work.
Android Manifest Permissions
Android permission system has different Protection Levels (1, 2); Normal permissions are granted to any app without user interaction while Signature|Privileged (SignatureOrSystem) permissions (whitelisted in /etc/permissions/privapp-permissions-*.xml
) are granted only to system apps. Both are granted when app is installed or on first startup (if system app) and configuration is saved in /data/system/packages.xml
file. Some signature permissions can be granted to non-system apps after user's approval using appops
.
Dangerous permissions are those which require user's approval to be granted or denied. User's choice is saved in /data/system/users/<User_ID>/runtime-permissions.xml
where device owner's User_ID is 0
(don't confuse it with UNIX DAC's UID).
Most of the manifest permissions are enforced by Android framework (system_server
) but some are mapped to GIDs; hence enforced by kernel. Permission to GID mapping is stored in /data/system/packages.list
.
How to Grant an App Unrequested Permission
You can modify above mentioned files to grant a permission which isn't requested by an app in its Manifest. I haven't tested with all permissions but this trick works (at least up to Pie) because Android framework doesn't verify the saved permission configuration vs. apps manifest files on every reboot (may be the changes are reverted back to actual during a scheduled maintenance task or when some app is installed or updated; I'm not sure).
In our case we want to grant android.permission.RECORD_AUDIO
to Termux which is a dangerous permission, so this is how you should edit your runtime-permissions.xml
followed by an immediate reboot:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<runtime-permissions fingerprint="...">
...
<shared-user name="com.termux">
<item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="0" />
<item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="0" />
<item name="android.permission.RECORD_AUDIO" granted="true" flags="0" />
</shared-user>
...
</runtime-permissions>
To confirm:
~$ pm dump com.termux | grep -A3 'runtime permissions:'
runtime permissions:
android.permission.READ_EXTERNAL_STORAGE: granted=true
android.permission.WRITE_EXTERNAL_STORAGE: granted=true
android.permission.RECORD_AUDIO: granted=true
Why SoX won't work?
That said, still SoX won't be able to record audio because (AFAIK) it's not using Android's Java APIs (android.media
) or native APIs (aaudio
/opensles
). It uses ALSA/OSS driver directly or through PulseAudio
which needs direct access to device interfaces in /dev/snd/
or /dev/{
audio,dsp*
}
and proc tree in /proc/asound/
. For details see Android Audio Architecture.
However direct kernel level access isn't a norm on Android, so you need root access. Apps with android.permission.MANAGE_VOICE_KEYPHRASES
are allowed to read /dev/snd/*
devices. It's a privileged signature level permission which is mapped to GID audio
(1005
). You can edit packages.xml
to get this permission granted:
<package name="com.termux" ... >
<perms>
<item name="android.permission.MANAGE_VOICE_KEYPHRASES" granted="true" flags="0" />
</perms>
</package>
<shared-user name="com.termux" ...>
<perms>
<item name="android.permission.MANAGE_VOICE_KEYPHRASES" granted="true" flags="0" />
</perms>
</shared-user>
And packages.list
:
com.termux ... 0 /data/user/0/com.termux default:targetSdkVersion=28... 1005,3003
But SELinux allows only privileged apps (having context priv_app
) to read files in /dev/snd
while /proc/asound/
isn't readable by apps at all, so you need to patch sepolicy
as well.
And even after that, configuring SoX to use ALSA/OSS/PA is up to you.
Non-Root Solutions
Instead of using ALSA directly, PulseAudio can also be configured to stream audio over TCP or UDP or UNIX sockets. That's how media playback works on Termux. See this issue. However capturing audio only work through Android APIs. You can install termux-api
package to use termux-microphone-record
command for audio recording. It uses MediaRecorder
class of Java API, or you may consider modifying SoX source to use Android's native APIs.
RELATED