How to grant an app a permission that isn't in its manifest for audio recording? Non rooted Moto G6 Play running Android 9.

I'm using Termux and would like to use Sox's rec command to record audio from the terminal.  Unfortunately, since Termux doesn't request the mic permission, it just records silence.  I can't grant Termux the permission in Settings because...well, it doesn't request it.  It's not in the app manifest, therefore Android (understandably) assumes it wouldn't know what to do with the permission if it had it and doesn't list "record audio" as an option.

Is there a way I can force Android to grant an app a permission it never asked for?
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/&lt;User_ID&gt;/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:

&lt;?xml version='1.0' encoding='UTF-8' standalone='yes' ?&gt;
&lt;runtime-permissions fingerprint="..."&gt;
  ...
  &lt;shared-user name="com.termux"&gt;
    &lt;item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="0" /&gt;
    &lt;item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="0" /&gt;
    &lt;item name="android.permission.RECORD_AUDIO" granted="true" flags="0" /&gt;
  &lt;/shared-user&gt;
  ...
&lt;/runtime-permissions&gt;


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:

    &lt;package name="com.termux" ... &gt;
        &lt;perms&gt;
            &lt;item name="android.permission.MANAGE_VOICE_KEYPHRASES" granted="true" flags="0" /&gt;
        &lt;/perms&gt;
    &lt;/package&gt;

    &lt;shared-user name="com.termux" ...&gt;
        &lt;perms&gt;
            &lt;item name="android.permission.MANAGE_VOICE_KEYPHRASES" granted="true" flags="0" /&gt;
        &lt;/perms&gt;
    &lt;/shared-user&gt;


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


How to Play Sound from Termux when using Linux?
How Android's permissions mapping with UIDs/GIDs works?