bindump
The bindump
utility is a little tool I've put together for my book, after realizing that there's no tool I know of, AOSP or other, which can map out which PIDs communicate over Binder with which. I needed this type of mapping for the chapter dealing with the Framework Services, as well as the long discussion on Binder Internals. The book is still not done (but, honestly, this year!), yet this tool is usable on its own. And is super simple, yes, though darn useful.
You can get the tool right here, as a tar with ARMv7 and ARMv8 (ARM64) binaries. The binaries should work on any Android 9 or higher. I've even worked around for Samsung oddities, and for Android 12 betas. As usual, you might want to check out the RSS feed, or follow my company's Twitter for more updates.
Why should I care?
If you've called Context.getSystemService(..)
, you've been using Binder (through proxy objects). The owning PID of most of these services is system_server
, but not always - notable exceptions being the phone
and batterypropregistrar
. Vendor installed services sometimes also run in their own processes.
If you want to get a better idea of who's talking to whom in your device - this is a pretty good tool for that. From the
So how do I use it?
Glad you asked. Usage couldn't be simpler. Unlike the original version of this tool, this now requires root privileges for the full power:
flame:/ $ /data/local/tmp/bindump
Usage: bindump [-h|-?]
bindump [ns] list
bindump [ns] check SERVICE
bindump [ns] users SERVICE # As per my 'bindump' tool
Where: [ns] is optionally 'binder' (default), 'hwbinder' or 'vndbinder'
This tool is part of the resources for 'Android Internals', Volume II
Free for non-commercial use at http://NewAndroidBook.com/
For commercial use (and pure C binder library) mail://products@Technologeeks.com
flame:/ $ /data/local/tmp/bindump check power
Service power: found
flame:/ $ /data/local/tmp/bindump check powerf
Service powerf: not found
1|flame:/ $ /data/local/tmp/bindump list
0: gsiservice
1: sip
..
It gets better when you have root. for example, you can now inspect the vndbinder namespace:
flame:/ # /data/local/tmp/bindump vndbinder list
0: media.ecoservice
1: airbrush_tpu
2: airbrush_faceauth
3: vendor.qcom.PeripheralManager
4: rlsservice
5: power.stats-vendor
6: display.qservice
7: android.hardware.citadel.ICitadeld
With the real kicker being "users" -
flame:/ # /data/local/tmp/bindump vndbinder users airbrush_tpu Service 'airbrush_tpu' is node 1014
User: 859 (/vendor/bin/hw/android.hardware.neuralnetworks@1.2-service-noronha)
Owner: 875 (/vendor/bin/hw/vendor.google.airbrush@1.0-service2-service-noronha)
User: 612 (/vendor/bin/vndservicemanager)
#
# Can also do 'all' for SERVICE name:
#
flame:/ $ /data/local/tmp/bindump vndbinder users all
Service 'media.ecoservice' is node 1346
Owner: 881 (media.hwcodec)
User: 849 (/vendor/bin/hw/android.hardware.camera.provider@2.4-service-google)
User: 612 (/vendor/bin/vndservicemanager)
Service 'airbrush_tpu' is node 1014
User: 859 (/vendor/bin/hw/android.hardware.neuralnetworks@1.2-service-noronha)
Owner: 875 (/vendor/bin/hw/vendor.google.airbrush@1.0-service2-service-noronha)
User: 612 (/vendor/bin/vndservicemanager)
Service 'airbrush_faceauth' is node 1010
Owner: 875 (/vendor/bin/hw/vendor.google.airbrush@1.0-servicelkid_untrusted_context=u:r:blkid_untrusted:s0)
User: 612 (/vendor/bin/vndservicemanager)
Service 'vendor.qcom.PeripheralManager' is node 951
User: 978 (/vendor/bin/hw/qcrildmp)
User: 994 (/vendor/bin/cnss-daemon)
Owner: 921 (/vendor/bin/pm-servicen)
User: 1010 (/vendor/bin/pm-proxycen)
User: 856 (/vendor/bin/hw/android.hardware.gnss@2.0-service-qtid_untrusted_context=u:r:blkid_untrusted:s0)
User: 612 (/vendor/bin/vndservicemanager)
Service 'rlsservice' is node 771
User: 867 (/vendor/bin/hw/android.hardware.sensors@2.0-serviceid_untrusted_context=u:r:blkid_untrusted:s0)
Owner: 874 (/vendor/bin/rlsservice.hardware.sensors@2.0-serviceid_untrusted_context=u:r:blkid_untrusted:s0)
User: 612 (/vendor/bin/vndservicemanager)
Service 'power.stats-vendor' is node 639
Owner: 863 (/vendor/bin/hw/android.hardware.power.stats@1.0-service.pixeled_context=u:r:blkid_untrusted:s0)
User: 620 (/vendor/bin/hw/citadeldhardware.power.stats@1.0-service.pixeled_context=u:r:blkid_untrusted:s0)
User: 612 (/vendor/bin/vndservicemanager)
Service 'display.qservice' is node 225
Owner: 655 (/vendor/bin/hw/android.hardware.graphics.composer@2.3-service-sm8150)
User: 612 (/vendor/bin/vndservicemanager)
Service 'android.hardware.citadel.ICitadeld' is node 8
User: 872 (/vendor/bin/hw/android.hardware.weaver@1.0-service.citadell)
User: 847 (/vendor/bin/hw/android.hardware.authsecret@1.0-service.citadel)
User: 621 (/vendor/bin/hw/android.hardware.keymaster@4.0-service.citadel-sm8150)
Owner: 620 (/vendor/bin/hw/citadeldhardware.keymaster@4.0-service.citadel-sm8150)
User: 612 (/vendor/bin/vndservicemanager)
'users' tells you which processes have handles to the service (real-time of course), AND who owns the node! This is REALLY useful. For example, try users power
to see who holds wakelocks, or users SurfaceFlinger
for whoever has views:
flame:/ # /data/local/tmp/bindump users SurfaceFlinger
Service 'SurfaceFlinger' is node 445
User: 4052 (com.topjohnwu.magisk)
User: 3034 (com.google.android.googlequicksearchbox:search)
User: 2223 (com.android.refreshratecontrol)
User: 1956 (com.breel.wallpapers19)
User: 1881 (com.android.systemui)
Owner: 653 (/system/bin/surfaceflinger)
User: 610 (/system/bin/servicemanager)
Note servicemanager
(or [vnd/hw]servicemanager
) are always users - that's because they need to give out the handle on lookup
How does it work?
Ah. An even better question. While a discussion of Binder is outside the scope of this little write-up (and, hey, it's in the book!), this tool's functionality is simple enough to explain in a few lines:
- Bind to the servicemanager, and check for the requested service. This automatically establishes a binder connection to the service
- Next, seek out
/sys/kernel/debug/binder/proc/$mypid . In it is a specific line of interest, in the form:ref xxxxxxx: desc yy node xxxxxxx s 1 w 1 d (null)
That "node" is what we're looking for. There are actually two node - ones for the service manager, which we can skip - it's always the first one. The second one is the one binding to our service. So we can extract the node number easily. - Finally, enumerate all entries in
/sys/kernel/debug/binder/proc - these are all processes which have binder handles. If they have the node as a ref, that means they're users of this very same service. If they have the Node in aNode:
line, they are the owner.
Example: healthd (owner of batterypropreg):
shell@htc_m8wl:/ $ cat /sys/kernel/debug/binder/proc/364
binder proc state:
proc 364
thread 364: l 02
node 17: u018317a0 c01830704 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 proc 25871 366
ref 15: desc 0 node 1 s 1 w 1 d (null) # Ref to ServiceManager
ref 777219: desc 1 node 777218 s 1 w 1 d ed9b5600 # Owner of batterypropreg
And that's that. Note: android 11 stock devices no longer support debugfs, per Google's dictum, but in 12 beta the debug data is back in
I'm working on improvements to adapt this to non published services (i.e. any binder nodes), as well as produce SVG output. And I'm always looking for suggestions. So stay tuned.
When will it not work?
- If you're not
root
- If you don't have the debugfs mounted under
/sys/kernel/debug (as is the case with stock Android 11 devices) AND there is no binder debug data in/dev/binderfs/binder_logs - If Binder wasn't compiled with debug data (which it is, by default)
License notes, etc
Free for non commercial use. Not open source, due to blatant ripoff of its previous version (which is, btw, why it now requires root - Google didn't like it either...). The original source of the previous version is here. The source is nothing fancy - it takes that of service.cpp
as a point of departure, but then embarks on its own journey. The updated source is a full re-write, using a Binder pure C interface I (painstakingly) wrote from scratch.
Shameless plug for the book, and RFC
The forever-delayed Volume II has a TON of detail about the framework services, and volume II covers the nooks and crannies of Binder in places where I betcha Dianne Hackborn herself (Love your work!) might feel uncomfortable ;-). The book is not out yet, but with MOXiI out of the way, and nothing to do locked down at home, it's finally progressing! In the interim, I encourage you to try out the tool (as well as the even more powerful JTrace) and shoot me an email (to j@) if you've any questions. Or comments. Or in general. All are welcome.