Steven De Bock
Steven De Bock

Reputation: 429

"Select AID" command is not always routed to HostApduService in Android HCE

Problem statement

I'm trying to understand why the "Select AID" command is not always successfully routed to the HostApduService of my HCE enabled application.

Sometimes, the "Select AID" is correctly routed to the HostApduService, as can be seen from the following logcat output:

07-11 20:11:36.386: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x18
07-11 20:11:36.396: D/HostEmulationManager(1486): notifyHostEmulationActivated
07-11 20:11:36.396: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x17
07-11 20:11:36.396: D/NxpNfcJni(1486): RoutingManager::stackCallback: NFA_CE_DATA_EVT; stat=0x0; h=0x301; data len=18
07-11 20:11:36.396: D/HostEmulationManager(1486): notifyHostEmulationData
07-11 20:11:36.396: D/HostEmulationManager(1486): Binding to service ComponentInfo{email.HCE/email.HCE.MyHCEService}
07-11 20:11:36.416: D/HostEmulationManager(1486): Waiting for new service.
07-11 20:11:36.466: D/MYHCESERVICE(25504): APDU RECEIVED
07-11 20:11:36.466: D/HostEmulationManager(1486): Sending data
07-11 20:11:37.276: E/SMD(284): DCD ON
07-11 20:11:37.436: D/NxpNfcJni(1486): RoutingManager::stackCallback: event=0x19
07-11 20:11:37.436: D/NxpNfcJni(1486): RoutingManager::stackCallback: NFA_DEACTIVATED_EVT, NFA_CE_DEACTIVATED_EVT
07-11 20:11:37.446: D/HostEmulationManager(1486): notifyHostEmulationDeactivated
07-11 20:11:37.446: D/MYHCESERVICE(25504): DISCONNECT
07-11 20:11:37.446: D/HostEmulationManager(1486): Unbinding from service ComponentInfo{email.HCE/email.HCE.MyHCEService}
07-11 20:11:37.446: D/MYHCESERVICE(25504): Disconnect by DEACTIVATION_LINK_LOSS
07-11 20:11:37.466: E/NfcNfa(1486): UICC/ESE[0x402] is not activated

However, more frequently, the "Select AID" command does not seem to arrive at the HostApduService. Its even worse, as there seems to be no activity at all from NxpNfcJni in the LogCat output. I consider NxpNfcJni to be the entry point given the excerpt from the LogCat output of a successful attempt.

It must be stated that the frequency of success is a lot lower then the frequency of failure.

Test Setup

Hereafter is a description of the HCE device and corresponding relevant code, followed by the description of the application that controls the reader.

1. HCE device

public class MyHCEService extends HostApduService {
    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
        Log.d("MYHCESERVICE", "APDU RECEIVED");
        return new byte[]{(byte)0x6F,(byte)0x25}; //returned byte array reduced for this example
    }

    @Override
    public void onDeactivated(int reason) {
        Log.d("MYHCESERVICE", "DISCONNECT");
        switch(reason) {
        case MyHCEService.DEACTIVATION_DESELECTED:
            Log.d("MYHCESERVICE", "Disconnect by DEACTIVATION_DESELECTED");
        case MyHCEService.DEACTIVATION_LINK_LOSS:
            Log.d("MYHCESERVICE", "Disconnect by DEACTIVATION_LINK_LOSS");
        }
    }    
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="email.HCE"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="22" />

    <uses-permission android:name="android.permission.NFC" />

    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    <uses-feature android:name="android.hardware.nfc.hce" android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyHCEService" android:exported="true"
         android:permission="android.permission.BIND_NFC_SERVICE">
            <intent-filter>
                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
            </intent-filter>
            <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
                       android:resource="@xml/apduservice"/>
        </service>

        <activity
            android:name=".ListBluetoothDevicesActivity"
            android:label="@string/app_name" 
            android:screenOrientation="portrait"
            android:configChanges="screenSize|orientation|keyboardHidden" >
        </activity>

    </application>

</manifest>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
           android:description="@string/servicedesc"
           android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aiddescription"
               android:category="other">
        <aid-filter android:name="11223344556677889900112233"/>
    </aid-group>
</host-apdu-service>

2. Reader application

byte[] CMD_SelectApp = { 
    0x00, //CLA 
    0xA4, //INS
    0x04, //P1
    0x00, //P2
    0x0D, //LC
    0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33 //AID
};
SCardContext _Context = new SCardContext();
_Context.Establish(SCardScope.System);
SCardReader _Reader = new SCardReader(_Context);
_Reader.Connect(SelectedReader, SCardShareMode.Direct, SCardProtocol.Any);
_Reader.Transmit(CMD_SelectApp, CMD_SelectApp.Length, RecvBuffer, ref ReceiveBufferLength);

Question

Does anyone see why the "Select AID" command is not always successful? Or someone that can give some indications to debug this one?

Upvotes: 1

Views: 3312

Answers (2)

Steven De Bock
Steven De Bock

Reputation: 429

It seems that by selecting only 1 type of polled cards for the ASK RDR 417 through the 'ASK RDR 417 (PC/SC) Properties' (see image below), the HostApduService is responding correctly and as expected.

I'm interested to know why, at first sight this seems to limit the reader capabilities.

ASK RDR417 (PC/SC) Properties

Upvotes: 1

Sam Edwards
Sam Edwards

Reputation: 894

I would highly suggest using this open source project which will allow you to test AID selection by running this app on another Android phone. It has been very helpful for me in the past. There are preprogrammed AIDs in the app for payment apps, but you can manually enter a custom AID as well. This is easier for testing (in my opinion) vs. having to use the USB reader.

https://github.com/doc-rj/smartcard-reader

enter image description here

Upvotes: 1

Related Questions