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
HostApduServicecomponents, 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: IndicatesSTATE_ON(NFC is fully powered and operational).STATE_OFFis 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
paymentorother. 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, MastercardA0000000041010, 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.