I am trying to create an application that transmits APDUs to a SIMCARD using the OMAPI libraries, but the OnConnected listener for SEService is never called.
I followed the structure I found here: https://android.googlesource.com/platform/cts/+/master/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
I wait up to 30 seconds to see if the OnConnectedListener method is called, but that never happens. I always get the error that I left in the code: throw new TimeoutException( "Service could not be connected after " + SERVICE_CONNECTION_TIME_OUT + "ms");
The SIMCARD I use contains the ARA-M applet, and the necessary SHA-1 keys, that is, the application obtains carrier privileges. In another application using the TelephonyManager libraries I have had success transmitting APDUs.
Please can you help me understand if I am doing something wrong? Do I need to declare some permission in the manifest of my application?
Thank you in advance.
I leave you part of the code that I implemented:
public class MainActivity extends AppCompatActivity [...]{
/*FOR OMAPI*/
private final Object serviceMutex = new Object();
private SEService seService;
private boolean connected = false;
private Timer connectionTimer;
private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask();
private final long SERVICE_CONNECTION_TIME_OUT = 30000;
//////////////////////////////////////////////////////////////////////////////
@Override
public void onCreate(Bundle savedInstanceState) {
[...]
setUp(getApplicationContext());
try {
waitForConnection();
} catch (TimeoutException e) {
throw new RuntimeException(e);
}
Reader[] readers = seService.getReaders();
byte [] apdu = {(byte)0x80, (byte)0x02, (byte)0xfC, (byte)0x00};
for (Reader reader : readers){
byte [] response = new byte[0];
try {
response = Util.internalTransmitAPDU(reader, apdu);
} catch (IOException e) {
throw new RuntimeException(e);
}
Log.i("response OMAPI", String.valueOf(response));
}
}
public void setUp(Context context){
seService = new SEService(context, new SynchronousExecutor(), mListener);
connectionTimer = new Timer();
connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
}
static class SynchronousExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
private final SEService.OnConnectedListener mListener = () -> {
synchronized (serviceMutex){
connected = true;
serviceMutex.notify();
Log.i("OMAPI", "EntraOnconnect");
}
private void waitForConnection() throws TimeoutException {
synchronized (serviceMutex) {
if (!connected) {
try {
serviceMutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!connected && !seService.isConnected()) {
throw new TimeoutException(
"Service could not be connected after " + SERVICE_CONNECTION_TIME_OUT
+ " ms");
}
if (connectionTimer != null) {
connectionTimer.cancel();
}
}
}
}
Try to use the
<uses-permission android:name="android.permission.READ_PHONE_STATE" />permission. Maybe this is missing.Could you also try to use a different
ExecutorinsteadSynchronousExecutor? E.g.:Maybe your code is blocked if not running in a different thread.