Skip to content

Don't catalog androidx DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION hack

context.registerReceiver() has had various behaviors and flags over different API releases, and androidx's ContextCompat attempts to unify its behavior to match that of API 33.

Before API 33, registerReceiver() took the name of a signature-level permission to gate whether intents could be sent to dynamically registered broadcast intent receivers. If no permission was specified, it was exported to the world.

In API 33, registerReceiver()'s flag argument gained explicit RECEIVER_EXPORTED and RECEIVER_NOT_EXPORTED controls. The use of RECEIVER_NOT_EXPORTED with no specified signature-level permissions means that the application intends to only send intents to itself, and reject them from elsewhere.

In order to emulate API 33's RECEIVER_NOT_EXPORTED flag on older APIs, androidx's ContextCompat makes use of the fact that a signature-level permission that no other app uses amounts to the same thing as being not exported. So, AAPT merges into the manifest:

<permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
    android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>

And then, on the older APIs, passes "${applicationId}.DYNAMIC_RECEIVER_ NOT_EXPORTED_PERMISSION" to registerReceiver()'s permission argument when RECEIVER_NOT_EXPORTED is specified.

This technique appears to work. But it has the downside that manifests built from androidx API 33 projects declare this additional arbitrary uses-permission, which looks a bit odd in F-Droid, since it's basically just an internal hack, rather than a real permission.

So, filter this out when generating the index.


This commit has not been runtime tested. If somebody here has a working fdroidserver setup and wants to give this a spin, com.wireguard.android.yaml will produce an APK with this permission.

Edited by Jason Donenfeld

Merge request reports