How to Audit Registered Broadcast Receivers and Intents on Android Using ADB

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.xml file. Modern Android versions restrict most implicit broadcast execution in the background to preserve battery life, but critical events (such as ACTION_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 call unregisterReceiver() 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.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.