The Clover Mini Contactless Performance Story — Part 1

Clover Platform
Clover Platform Blog
4 min readJun 4, 2020

by Jacob Abrams

This story covers just a fraction of the journey we set on when we decided to build our first EMV-compliant, NFC contactless-enabled payment devices: Clover Mini and Clover Mobile.

Faster transactions equals happier merchants and customers

Payment terminals are required to pass a long list of certification tests before they land in the hands of merchants. MasterCard in particular has very strict performance requirements for contactless (aka NFC) transactions. MasterCard requires the total time spent by the payment terminal to be less than 100 milliseconds from the transmission of the first contactless packet to the last packet and audio tone indicating completion. They want to minimize the amount of time consumers have to hold their card or phone next to the payment terminal before the payment is complete. Faster transactions equals happier merchants and customers. Since payment terminal manufacturers such as Clover cannot control the time spent by the card or phone during the transaction, that time is excluded from the measurements during certification. Our initial contactless test results for Clover Mini and Mobile came in at over 300 milliseconds, nowhere near the 100 millisecond requirement.

Beep latency

For security reasons Clover uses a separate secure processor to handle all sensitive card data. This secure processor communicates with the card during a contactless transaction but it has no display or speaker itself; our primary application processor controls the display and speaker. The two processors send each other messages over USB to complete a payment.

We began working on improving the performance of contactless payments by adding tracing to all the significant events that take place during a contactless payment. We noticed that there was a significant delay from the end of the transaction to actually hearing the beep come out the speaker. This audio delay was over 100 milliseconds in and of itself.

My coworkers began working on the problem and they made one critical change to help bring the time down. They switched from using USB messages between the processors to using an available GPIO we had connected between the processors to send the signal that it was time to play the contactless beep. The GPIO generated an interrupt that was received much more quickly than the USB message. However, the time between invoking the Android Java play sound function and the actual emitting of the sound from the speaker was still measured to be at least 85 milliseconds. We had to find a way to reduce the audio latency in the Android OS. One coworker suggested an interesting idea of starting to play the sound before it was needed but at zero volume and then increasing the volume to an audible level at the moment the beep sound was needed. I gave it a try but the performance improvement was negligible.

Circumventing the Android Java APIs

At this point I guessed that using the Android Java APIs to play sounds might be the source of the delay. Operating systems are composed of many parts and the Android OS is a combination of the linux kernel with a lot of user-mode code on top that provide easier to use Java APIs for app developers. Using the Android Java APIs to play sounds involves sending interprocess messages from your app process to the AudioFlinger in a system process which eventually processes the audio and sends it to the kernel audio driver. I decided to investigate how native Linux apps play sound since Android is based on Linux. After some searching I read about the ALSA API and then discovered in the AOSP external projects an open source TinyALSA app that used the ALSA API to play sound natively. The test results were promising. There was very low latency when using the ALSA API to play sound. I proceeded to build a JNI interface between the Java Android app I had built to manage secure processor communication to C code which used the ALSA API based on TinyALSA. The results were impressive — the audio latency was down from 85 milliseconds to about 7 milliseconds.

Even with this new solution, I noticed rare instances of a large delay of hundreds of milliseconds to play the sound. From playing with the device it soon became apparent that if any other sound was played by Android recently that would affect the performance of the native ALSA sound player. I searched through the AudioFlinger code for keywords like sleep, delay, and milliseconds. I discovered that a standby time of 3 seconds was used to retain a lock on the audio driver so that AudioFlinger need not re-initialize the driver. Reducing this lock time to a couple hundred milliseconds eliminated the contention. This change would, of course, affect the audio performance of audio intensive Android applications like games, but since our device was not meant for gaming the drawbacks were minimal.

…And yet so far from 100 ms

While we were able to save significant milliseconds by reducing the contactless beep delay, our actions were not nearly enough to get us down to 100 ms. Most of the code running on the secure processor during contactless transactions was in the various software libraries that Clover didn’t author but had assembled from a variety of vendors and open source projects. This meant we were confronted with analyzing large bodies of code we were not particularly familiar with.

The story doesn’t end here… In part 2 of this story, I describe how we faced this challenge as we reached near completion on building the Clover Mini and Clover Mobile.

--

--