Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How mature is the Android NFC ISODep support?

I understand that this is a "discussion" topic that has no definite answer, but I would really like some feedback on what to expect when developing NFC APPs for Android, in particular using IsoDep to communicate with DESFire cards using APDU frames.

  • Can I expect that the same APDU frames sent to a particular DESFire card responds identically across Android Devices and versions?
  • What Android versions and devices should I test on as a minimum to be reasonably well covered?
  • Is it common with bugs or regressions in the Android drivers or can I expect that these are rooted out a long time ago?
  • What is the earliest version of Android you recommend supporting to avoid too much trouble?

So far my experience has been surprisingly mixed (3 devices, 3 differences) and I would really like to hear from other developers. For example: The same APDU commands that work on a S3 (Android 4.1.2) does not work on an S4 (Android 4.3) ("wrong length" failure on the 3rd autenticate handshake, everything OK until then). These phones have different NFC chipsets, but I did not expect differences on the abstraction level of APDU frames.

like image 442
Karl Ivar Dahl Avatar asked Dec 03 '13 09:12

Karl Ivar Dahl


2 Answers

This is indeed a discussion topic, still I think it's relevant to Android NFC developers and I will, therefore, give my experience report here:

  • Can I expect that the same APDU frames sent to a particular DESFire card responds identically across Android Devices and versions?

Yes, but only for APDU commands that fulfill the requirements of ISO/IEC 7816-4 with some additional restrictions (e.g. not all devices support extended length APDUs, some devices seem to have problems with case-1 APDUs).

Also there are some known bugs in the latest version of the Broadcom NFC stack (see below).

  • What Android versions and devices should I test on as a minimum to be reasonably well covered?

The most problems I experienced so far were with Samsung devices with the Broadcom NFC chipset. Though not APDU-related, particularly when it comes to using MIFARE Classic, they behave quite differently than other devices with Broadcom chipset. For instance the S4 blocks MIFARE Classic tags at system level and, therefore, does not permit to read the tags (N)UID. (Reading data from MF Classic would not be possible with Broadcom chipsets anyways...)

Regarding testing, I would therefore suggest at least one Nexus device for each NFC controller (i.e. one with NXP chipset and one with Broadcom chipset) and the same for one or two other handset manufacturers. (For Samsung the devices with NXP chipset behave very similar to the Nexus devices, so I guess you the Nexus S/Galaxy Nexus and e.g. the S3 can be seen as equivalent when it comes to the NFC reader/writer mode experience.)

Regarding Android platforms I would stick to those platforms on which you have the most users. (And also those platforms where you have high rates of uninstalls.)

  • Is it common with bugs or regressions in the Android drivers or can I expect that these are rooted out a long time ago?

As I meantioned before there are some known issues with the Broadcom NFC stack. Particularly when it comes to MIFARE DESFire, there is a known problem that the NFC stack sends arbitrary APDU-based commands to the card after passing it to an app. As a consequence, those commands may interfere with ongoing communication between the card and that app (e.g. force APDU-based communication mode instead of native command mode, change application/file selection, etc). See this bug report and this stackoverflow question for further details.

And looking through the bug tracker, there are definitely more unresolved issues.

  • What is the earliest version of Android you recommend supporting to avoid too much trouble?

With regard to APDU-based communication (with DESFire or with other cards), API 10 (Android 2.3.3) and later work okay. When it comes to usability of the NFC API (besides simple APDU exchange) and to nice app design, I would stick to Android 4.0.3 and later. But keep in mind that the newest platforms particularly Android 4.3 and Android 4.4 introduced many odd behaviors/bugs/("features"?).

To get a feeling for what Android versions users with NFC devices currently have, I'll share the current device installs distribution for NFC TagInfo (though this may be slightly biased as NFC TagInfo is not intended for the average user):

  1. Android 4.1: 36%
  2. Android 4.3: 21%
  3. Android 4.2: 19%
  4. Android 4.4: 18%
  5. Android 4.0.3 - 4.0.4: 4%
  6. Android 2.3.3 - 2.3.7: 2%
  7. Android 4.0 - 4.0.2: 0%
  8. Android 3.2: 0%
like image 75
Michael Roland Avatar answered Sep 30 '22 18:09

Michael Roland


This answer is related to your concrete problem with APDUs working on one device but not working on others. As Michael Roland pointed out, there is the problem that devices that use the NCI NFC stack, frequently send APDUs that might interfere with APDUs sent by your application. The problem is related to an incorrect implementation of the presence check in this stack and is documented here. This is especially a problem when executing the authenticate procedure on DESFire cards as it consists of multiple APDUs and will fail if interrupted by unrelated APDUs. However, there is a workaround for devices running on Android Version >= 4.4 (API level >= 19). On these devices you can use the enableReaderMode method with the EXTRA_READER_PRESENCE_CHECK_DELAY extra to configure the frequency of the presence check. By increasing the delay you can reduce the probability of interfering with your application APDUs.

E.g.:

    Bundle options = new Bundle();
    options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 5000);

    getNfcAdapter().enableReaderMode(
            this,
            new ReaderCallback() {
                @Override
                public void onTagDiscovered(final Tag tag) {
                    // ... authenticate ...
                }
            },
            NfcAdapter.FLAG_READER_NFC_A
                    | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, options);
like image 36
MarkusM Avatar answered Sep 30 '22 16:09

MarkusM