How to Inspect NFC Controller States and Host Card Emulation on Android Using ADB dumpsys nfc

Contactless transactions on mobile devices—including mobile payments via Google Wallet, tap-to-ride transit card interactions, enterprise access badges, and smart posters—rely on Near Field Communication (NFC) hardware controllers. In modern Android devices, contactless services are powered by Host Card Emulation (HCE), an architectural framework that routes incoming ISO/IEC 14443 contactless smart card commands directly to user-space applications without requiring a physical carrier SIM or embedded secure element (eSE). When debugging an NFC payment application that fails to complete Point of Sale (POS) handshakes, experiences Application Identifier (AID) conflicts, or suffers from radio frequency discovery timeouts, developers need deep protocol-level diagnostics. Using the Android Debug Bridge (ADB), the internal dumpsys nfc command exposes live RF polling loops, registered HCE routing tables, and NFC controller states directly from the Android runtime.

Understanding the Android NFC and Host Card Emulation Architecture

The Android NFC subsystem operates through several interdependent hardware and software layers:

  • NFC Controller Interface (NCI): The standardized protocol connecting the Android host application processor to the physical NFC chipset (e.g. NXP, Broadcom, or STMicroelectronics).
  • RF Discovery Loop: The continuous polling cycle where the NFC radio alternates between Reader/Writer mode, Peer-to-Peer (P2P), and Card Emulation listening modes across varying modulation standards (NFC-A, NFC-B, NFC-F).
  • Routing Table: The hardware-level routing matrix inside the NFC controller that determines whether incoming RF transactions are routed to the host CPU (HCE), the embedded Secure Element (eSE), or the UICC/SIM card based on Application Identifiers (AIDs).
  • CardEmulationManagerService: The system service managing registered third-party HostApduService components, default payment apps, and AID category priorities.

Connecting via ADB and Dumping Complete NFC State

To inspect the status of the NFC subsystem, connect your Android device with USB debugging enabled and run the diagnostic command:

adb shell dumpsys nfc

The output reports the complete internal status of NfcService and CardEmulationManager. To save the dump for detailed offline inspection:

adb shell dumpsys nfc > nfc_service_dump.txt

Auditing NFC Radio State and Polling Modes

To verify whether the physical NFC controller is active, initialized, and actively executing its RF discovery loop:

adb shell dumpsys nfc | grep -E "mState|mIsZeroClick|mDiscoveryTech"

Key parameters to audit include:

  • mState=3: Indicates STATE_ON (NFC is fully powered and operational). STATE_OFF is 1, while intermediate states indicate transitioning power modes.
  • mDiscoveryTech: Bitmask indicating active RF polling protocols (such as Type A, Type B, or Type F felica).
  • mScreenState: Indicates the current screen lock posture (e.g. SCREEN_STATE_ON_UNLOCKED). By default, Android blocks HCE card emulation transactions when the device is locked, unless an application explicitly declares secure lock-screen emulation support.

Inspecting Host Card Emulation (HCE) Routing Tables and AIDs

When an external POS terminal or transit gate transmits a SELECT AID Application Protocol Data Unit (APDU), the NFC controller checks its internal routing table to identify the matching application package. To inspect all registered HCE services and their configured AIDs:

adb shell dumpsys nfc | grep -A 35 "Registered HCE services for current user:"

Each entry details:

  • Component: The exported service name implementing android.nfc.cardemulation.HostApduService (e.g. com.google.android.gms/.pay.hce.PaymentService).
  • Category: Classified as either payment or other. Android strictly permits only one default payment application at any given time.
  • AIDs: The specific hexadecimal Application Identifiers claimed by the app (e.g. Visa A0000000031010, Mastercard A0000000041010, or custom transit protocols).

Diagnosing Default Payment App and AID Conflicts

If multiple apps claim the same payment AID, the Android framework routes transactions strictly to the user-selected default payment service. To audit the active payment service:

adb shell dumpsys nfc | grep -A 5 "mDefaultPaymentService"

You can also query the persistent Android secure settings database directly to verify which application holds default payment authority:

adb shell settings get secure nfc_payment_default_component

To programmatically assign a test application as the primary payment handler during automated regression runs:

adb shell settings put secure nfc_payment_default_component "com.example.transitapp/.services.CustomHceService"

Tracing Live APDU Exchanges and Transaction Logs

When troubleshooting transaction failures or timing timeouts (such as transactions taking longer than the 500 ms gate threshold required by public transit turnstiles), stream real-time NFC logcat messages:

adb logcat -v time -s NfcService:V HostEmulationManager:V BrcmNfcJni:V

Look for log lines capturing the APDU handshake:

  • SELECT AID: A0000000031010: The terminal requests the payment app.
  • HCE service selected: Android dispatches the intent to the user-space process.
  • processCommandApdu(): Application generates the cryptographic response block.

Using dumpsys nfc alongside real-time logcat streaming gives Android engineers complete visibility into contactless smart card lifecycles, enabling rapid resolution of AID conflicts, power state anomalies, and POS handshake timeouts.

Get the best tech tips delivered straight to your inbox.

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