In the Android operating system, inter-process communication (IPC) and system event notifications rely heavily on the broadcast messaging subsystem. Applications listen for system-wide announcements—such as network connectivity changes, battery level transitions, SMS arrivals, device reboots, or custom application events—by implementing Broadcast Receivers. However, improper receiver implementation can degrade system performance through frequent background wakeups, induce memory leaks via unreleased dynamic listeners, or expose sensitive data via insecure, exported intents.
For mobile software engineers, QA testers, and security auditors, inspecting the active broadcast landscape is essential for diagnosing unhandled events and identifying security vulnerabilities. Using the Android Debug Bridge (ADB) to interface with the Activity Manager’s diagnostic dumping engine (dumpsys activity broadcasts), you can query all registered static and dynamic receivers, inspect active intent filters, trace pending broadcast queues, and simulate system broadcasts directly from your development workstation.
Understanding Android Broadcast Receiver Types
Android categorizes broadcast receivers based on how and where they are declared:
- Manifest-Declared (Static) Receivers: Registered inside the application’s
AndroidManifest.xmlfile. Modern Android versions restrict most implicit broadcast execution in the background to preserve battery life, but critical events (such asACTION_BOOT_COMPLETED) still rely on manifest registration. - Context-Registered (Dynamic) Receivers: Registered dynamically at runtime using
Context.registerReceiver(). These receivers exist in memory only while their parent component (Activity or Service) remains active. If an activity fails to callunregisterReceiver()in its lifecycle teardown, it leaks memory and continues intercepting broadcasts. - Ordered Broadcasts: Broadcasts delivered to receivers sequentially based on declared priority (e.g., allowing an app to intercept and suppress an incoming notification before lower-priority receivers process it).
Dumping the Complete Broadcast Registry via ADB
To inspect all broadcast queues, registered receivers, and sticky intents across the Android operating system, execute dumpsys activity broadcasts:
adb shell dumpsys activity broadcasts
Because the full output spans thousands of lines of system telemetry, redirect the stream to a text file for inspection:
adb shell dumpsys activity broadcasts > broadcasts_dump.txt
Filtering Broadcasts for a Specific Application Package
When auditing a specific app (e.g., com.example.myapp), searching through system-wide logs is inefficient. Use grep to isolate receivers registered by your target package:
adb shell dumpsys activity broadcasts | grep -A 15 "com.example.myapp"
The console outputs the registered receiver’s class name, process ID (PID), user ID (UID), and active intent filters:
ReceiverList{4a2f8b0 14502 com.example.myapp/10234 u0}
app=ProcessRecord{5c1e9a0 14502:com.example.myapp/u0a234} pid=14502 uid=10234 user=0
Filter #0: IntentFilter{8b3c10e ...}
Action: "android.net.conn.CONNECTIVITY_CHANGE"
Action: "com.example.myapp.ACTION_REFRESH_DATA"
This output reveals that process 14502 has an active dynamic receiver registered to intercept both network connectivity changes and an internal data refresh action.
Auditing Broadcast Queues and Delivery Delays
If an application appears slow to respond to incoming system events, inspect the state of the active broadcast delivery queues:
adb shell dumpsys activity broadcasts | grep -A 10 "Active broadcasts"
Android maintains two primary broadcast queues:
- foreground queue: High-priority broadcasts intended for immediate UI presentation (timeout limit is 10 seconds before triggering an ANR).
- background queue: Standard broadcasts for background worker tasks (timeout limit is 60 seconds).
If the queue lists multiple stalled broadcasts, an application’s onReceive() method is performing heavy synchronous work (such as disk I/O or network requests) on the main thread, blocking subsequent broadcasts.
Auditing Exported Receivers for Security Vulnerabilities
In mobile application security auditing, manifest receivers configured with android:exported="true" without explicit signature permissions represent potential attack vectors. Third-party rogue applications can spoof intents to trigger unintended internal routines.
To query all receivers declared by an installed package directly from the package manager:
adb shell dumpsys package com.example.myapp | grep -A 12 "Receivers:"
Review the output to confirm that non-public receivers are marked as unexported or protected by custom permissions.
Simulating and Firing Broadcast Events with ADB
One of the primary benefits of ADB broadcast debugging is the ability to trigger broadcast intents manually without physically altering device hardware (e.g., without disconnecting Wi-Fi or unplugging chargers).
1. Simulating Battery Low Broadcast
adb shell am broadcast -a android.intent.action.BATTERY_LOW
2. Simulating Device Boot Completion
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -p com.example.myapp
(Using -p scopes the broadcast explicitly to your target package, avoiding unwanted system-wide triggers).
3. Sending Custom Intents with String Extras
To trigger a custom internal receiver and pass test payloads:
adb shell am broadcast -a com.example.myapp.ACTION_UPDATE_CONFIG --es "config_key" "debug_mode" --ez "force_refresh" true
The Activity Manager confirms transmission:
Broadcasting: Intent { act=com.example.myapp.ACTION_UPDATE_CONFIG (has extras) }
Broadcast completed: result=0
Auditing and triggering broadcast receivers via ADB ensures Android applications manage event-driven background processing efficiently and securely.