aboutsummaryrefslogtreecommitdiffstats
path: root/com/nxp/nfc/NxpNfcAdapter.java
blob: bafa19a1e1d8dfc117786f8a978be02720f2d2e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
/*
*
*  The original Work has been changed by NXP Semiconductors.
*
*  Copyright (C) 2013-2019 NXP Semiconductors
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/
package com.nxp.nfc;

import java.util.HashMap;
import java.util.Map;
import android.nfc.INfcAdapter;
import android.nfc.NfcAdapter;
import android.nfc.INfcAdapterExtras;
import android.os.IBinder;
import android.os.ServiceManager;

import java.io.IOException;
import android.os.UserHandle;
import android.os.RemoteException;
import com.nxp.nfc.gsma.internal.INxpNfcController;

import android.util.Log;
import java.util.List;
public final class NxpNfcAdapter {
    private static final String TAG = "NXPNFC";
    private static int ALL_SE_ID_TYPE = 0x07;
    // Guarded by NfcAdapter.class
    static boolean sIsInitialized = false;

    /**
     * The NfcAdapter object for each application context.
     * There is a 1-1 relationship between application context and
     * NfcAdapter object.
     */
    static HashMap<NfcAdapter, NxpNfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class

    // Final after first constructor, except for
    // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
    // recovery
    private static INfcAdapter sService;
    private static INxpNfcAdapter sNxpService;

    private NxpNfcAdapter() {
    }
    /**
     * Returns the NxpNfcAdapter for application context,
     * or throws if NFC is not available.
     * @hide
     */
    public static synchronized NxpNfcAdapter getNxpNfcAdapter(NfcAdapter adapter) {
        if (!sIsInitialized) {
            if (adapter == null) {
                Log.v(TAG, "could not find NFC support");
                throw new UnsupportedOperationException();
            }
            sService = getServiceInterface();
            if (sService == null) {
                Log.e(TAG, "could not retrieve NFC service");
                throw new UnsupportedOperationException();
            }
            sNxpService = getNxpNfcAdapterInterface();
             if (sNxpService == null) {
                Log.e(TAG, "could not retrieve NXP NFC service");
                throw new UnsupportedOperationException();
            }
            sIsInitialized = true;
        }
        NxpNfcAdapter nxpAdapter = sNfcAdapters.get(adapter);
        if (nxpAdapter == null) {
            nxpAdapter = new NxpNfcAdapter();
            sNfcAdapters.put(adapter, nxpAdapter);
        }
        return nxpAdapter;
    }

    /** get handle to NFC service interface */
    private static INfcAdapter getServiceInterface() {
        /* get a handle to NFC service */
        IBinder b = ServiceManager.getService("nfc");
        if (b == null) {
            return null;
        }
        return INfcAdapter.Stub.asInterface(b);
    }

    /**
     * NFC service dead - attempt best effort recovery
     * @hide
     */
    private static void attemptDeadServiceRecovery(Exception e) {
        Log.e(TAG, "Service dead - attempting to recover",e);
        INfcAdapter service = getServiceInterface();
        if (service == null) {
            Log.e(TAG, "could not retrieve NFC service during service recovery");
            // nothing more can be done now, sService is still stale, we'll hit
            // this recovery path again later
            return;
        }
        // assigning to sService is not thread-safe, but this is best-effort code
        // and on a well-behaved system should never happen
        sService = service;
        sNxpService = getNxpNfcAdapterInterface();
        return;
    }
    /**
     * Set listen mode routing table configuration for Mifare Desfire Route.
     * routeLoc is parameter which fetch the text from UI and compare
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     *
     * @throws IOException If a failure occurred during Mifare Desfire Route
     * set.
     */
    public void MifareDesfireRouteSet(String routeLoc, boolean fullPower,
                                      boolean lowPower, boolean noPower)
        throws IOException {
      try {
        int seID = 0;
        boolean result = false;
        if (routeLoc.equals(NfcConstants.UICC_ID)) {
          seID = NfcConstants.UICC_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.UICC2_ID)) {
          seID = NfcConstants.UICC2_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.SMART_MX_ID)) {
          seID = NfcConstants.SMART_MX_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.HOST_ID)) {
          seID = NfcConstants.HOST_ID_TYPE;
        } else {
          Log.e(TAG, "confMifareDesfireProtoRoute: wrong default route ID");
          throw new IOException(
              "confMifareProtoRoute failed: Wrong default route ID");
        }
        Log.i(TAG, "calling Services");
        sNxpService.MifareDesfireRouteSet(seID, fullPower, lowPower, noPower);
      } catch (RemoteException e) {
        Log.e(TAG, "confMifareDesfireProtoRoute failed", e);
        attemptDeadServiceRecovery(e);
        throw new IOException("confMifareDesfireProtoRoute failed");
      }
    }
    /**
     * Set listen mode routing table configuration for MifareCLTRouteSet.
     * routeLoc is parameter which fetch the text from UI and compare
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     *
     * @throws IOException If a failure occurred during Mifare CLT Route set.
     */
    public void MifareCLTRouteSet(String routeLoc, boolean fullPower,
                                  boolean lowPower, boolean noPower)
        throws IOException {
      try {
        int seID = 0;
        boolean result = false;
        if (routeLoc.equals(NfcConstants.UICC_ID)) {
          seID = NfcConstants.UICC_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.UICC2_ID)) {
          seID = NfcConstants.UICC2_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.SMART_MX_ID)) {
          seID = NfcConstants.SMART_MX_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.HOST_ID)) {
          seID = NfcConstants.HOST_ID_TYPE;
        } else {
          Log.e(TAG, "confMifareCLT: wrong default route ID");
          throw new IOException("confMifareCLT failed: Wrong default route ID");
        }
        sNxpService.MifareCLTRouteSet(seID, fullPower, lowPower, noPower);
      } catch (RemoteException e) {
        Log.e(TAG, "confMifareCLT failed", e);
        attemptDeadServiceRecovery(e);
        throw new IOException("confMifareCLT failed");
      }
    }
    /**
     * This api returns the CATEGORY_OTHER (non Payment)Services registered by
     * the user along with the size of the registered aid group. This api has to
     * be called when aid routing full intent is broadcast by the system.
     * <p>This gives the list of both static and dynamic card emulation services
     * registered by the user.
     * <p> This api can be called to get the list of offhost and onhost
     * cardemulation services registered by the user. <ul> <li> If the category
     * is CATEGORY_PAYMENT than null value is returned. <li> If there are no non
     * payment services null value is returned.
     * </ul>
     * @param UserID  The user id of current user
     * @param category The category i.e. CATEGORY_PAYMENT , CATEGORY_OTHER
     * @return The List of NfcAidServiceInfo objects
     */
    public List<NfcAidServiceInfo> getServicesAidInfo (int UserID , String category) throws IOException{
        try {
            return sNxpService.getServicesAidInfo(UserID ,category);
        }catch(RemoteException e)
        {
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return null;
        }
    }
    /**
     * @hide
     */ 
    private static INxpNfcAdapter getNxpNfcAdapterInterface() {
        if (sService == null) {
            throw new UnsupportedOperationException("You need a reference from NfcAdapter to use the "
                    + " NXP NFC APIs");
        }
        try {
            IBinder b = sService.getNfcAdapterVendorInterface("nxp");
            if (b == null) {
                return null;
            }
            return INxpNfcAdapter.Stub.asInterface(b);
        } catch (RemoteException e) {
            return null;
        }
    }

    /**
     * Change poll and listen technology
     * Generic API is use to disable polling and enable speicific listening technology
     * @param binder,pollTech, listenTech.
     * @return void
     * @hide
     */
    public void changeDiscoveryTech(IBinder binder, int pollTech, int listenTech) throws IOException {
        try {
            sNxpService.changeDiscoveryTech(binder, pollTech, listenTech);
        } catch (RemoteException e) {
            Log.e(TAG, "changeDiscoveryTech failed", e);
        }
    }
     /**
     * @hide
     */
    public INxpNfcAdapterExtras getNxpNfcAdapterExtrasInterface() {
        if (sNxpService == null) {
            throw new UnsupportedOperationException("You need a context on NxpNfcAdapter to use the "
                    + " NXP NFC extras APIs");
        }
        try {
            return sNxpService.getNxpNfcAdapterExtrasInterface();
        } catch (RemoteException e) {
        Log.e(TAG, "getNxpNfcAdapterExtrasInterface failed", e);
        attemptDeadServiceRecovery(e);
            return null;
        }catch(Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }


   /**
     * This is the first API to be called to start or stop the mPOS mode
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * <li>This api shall be called only Nfcservice is enabled.
     * <li>This api shall be called only when there are no NFC transactions ongoing
     * </ul>
     * @param  pkg package name of the caller
     * @param  on Sets/Resets the mPOS state.
     * @return whether the update of state is
     *          success or busy or fail.
     *          MPOS_STATUS_BUSY
     *          MPOS_STATUS_REJECTED
     *          MPOS_STATUS_SUCCESS
     * @throws IOException If a failure occurred during reader mode set or reset
     */
    public int mPOSSetReaderMode (String pkg, boolean on) throws IOException {
        try {
            return sNxpService.mPOSSetReaderMode(pkg, on);
        } catch(RemoteException e) {
            Log.e(TAG, "RemoteException in mPOSSetReaderMode (int state): ", e);
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            throw new IOException("RemoteException in mPOSSetReaderMode (int state)");
        }
    }

    /**
     * This is provides the info whether mPOS mode is activated or not
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * <li>This api shall be called only Nfcservice is enabled.
     * <li>This api shall be called only when there are no NFC transactions ongoing
     * </ul>
     * @param  pkg package name of the caller
     * @return TRUE if reader mode is started
     *          FALSE if reader mode is not started
     * @throws IOException If a failure occurred during reader mode set or reset
     */
    public boolean mPOSGetReaderMode (String pkg) throws IOException {
        try {
            return sNxpService.mPOSGetReaderMode(pkg);
        } catch(RemoteException e) {
            Log.e(TAG, "RemoteException in mPOSGetReaderMode (): ", e);
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            throw new IOException("RemoteException in mPOSSetReaderMode ()");
        }
    }

    /**
     * This API is called by application to stop RF discovery
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * <li>This api shall be called only Nfcservice is enabled.
     * </ul>
     * @param  pkg package name of the caller
     * @param  mode
     *         LOW_POWER
     *         ULTRA_LOW_POWER
     * @return None
     * @throws IOException If a failure occurred during stop discovery
    */
    public void stopPoll(String pkg, int mode) throws IOException {
        try {
            sNxpService.stopPoll(pkg, mode);
        } catch(RemoteException e) {
            Log.e(TAG, "RemoteException in stopPoll(int mode): ", e);
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            throw new IOException("RemoteException in stopPoll(int mode)");
        }
    }

    /**
     * This API is called by application to start RF discovery
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * <li>This api shall be called only Nfcservice is enabled.
     * </ul>
     * @param  pkg package name of the caller
     * @return None
     * @throws IOException If a failure occurred during start discovery
    */
    public void startPoll(String pkg) throws IOException {
        try {
            sNxpService.startPoll(pkg);
        } catch(RemoteException e) {
            Log.e(TAG, "RemoteException in startPoll(): ", e);
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            throw new IOException("RemoteException in startPoll()");
        }
    }

   /**
    * Get the handle to an INxpNfcController Interface
    * @hide
    */
    public INxpNfcController getNxpNfcControllerInterface() {
        if(sService == null) {
            throw new UnsupportedOperationException("You need a reference from NfcAdapter to use the "
                    + " NXP NFC APIs");
        }
        try {
            return sNxpService.getNxpNfcControllerInterface();
        }catch(RemoteException e) {
            return null;
        }
    }
     /**
     * Get the Active Secure Element List
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     *
     * @throws IOException If a failure occurred during the getActiveSecureElementList()
     */
    public String[] getActiveSecureElementList(String pkg) throws IOException {
        int [] activeSEList;
        String [] arr;
        try{
            Log.d(TAG, "getActiveSecureElementList-Enter");
            activeSEList = sNxpService.getActiveSecureElementList(pkg);
            if (activeSEList!=null && activeSEList.length != 0)
            {
                arr= new String[activeSEList.length];
                for(int i=0;i<activeSEList.length;i++)
                {
                    Log.e(TAG, "getActiveSecureElementList activeSE[i]" + activeSEList[i]);
                    if(activeSEList[i]==NfcConstants.SMART_MX_ID_TYPE)
                    {
                        arr[i]= NfcConstants.SMART_MX_ID;
                    }
                    else if(activeSEList[i]==NfcConstants.UICC_ID_TYPE)
                    {
                        arr[i]= NfcConstants.UICC_ID;
                    }
                    else if(activeSEList[i]==NfcConstants.UICC2_ID_TYPE)
                    {
                        arr[i]= NfcConstants.UICC2_ID;
                    }
                    else {
                        throw new IOException("No Secure Element Activeted");
                    }
                }
            } else {
                arr = new String[0];
            }
            return arr;
        } catch (RemoteException e) {
            Log.e(TAG, "getActiveSecureElementList: failed", e);
            attemptDeadServiceRecovery(e);
            throw new IOException("Failure in deselecting the selected Secure Element");
        }
    }

    /**
     * Set listen mode routing table configuration for Default Route.
     * routeLoc is parameter which fetch the text from UI and compare
     * * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * @throws IOException If a failure occurred during Default Route Route set.
     */
    public void DefaultRouteSet(String routeLoc, boolean fullPower,
                                boolean lowPower, boolean noPower)
        throws IOException {
      try {
        int seID = 0;
        boolean result = false;
        if (routeLoc.equals(NfcConstants.UICC_ID)) {
          seID = NfcConstants.UICC_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.UICC2_ID)) {
          seID = NfcConstants.UICC2_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.SMART_MX_ID)) {
          seID = NfcConstants.SMART_MX_ID_TYPE;
        } else if (routeLoc.equals(NfcConstants.HOST_ID)) {
          seID = NfcConstants.HOST_ID_TYPE;
        } else {
          Log.e(TAG, "DefaultRouteSet: wrong default route ID");
          throw new IOException(
              "DefaultRouteSet failed: Wrong default route ID");
        }
        sNxpService.DefaultRouteSet(seID, fullPower, lowPower, noPower);
      } catch (RemoteException e) {
        Log.e(TAG, "confsetDefaultRoute failed", e);
        attemptDeadServiceRecovery(e);
        throw new IOException("confsetDefaultRoute failed");
      }
    }

    /**
     * This api is called by applications to get the maximum routing table for
     * AID registration The returned value doesn't provide the current remaining
     * size available for AID. This value depends on the size available in NFCC
     * and is constant. <p>Requires {@link android.Manifest.permission#NFC}
     * permission.
     * @return maximum routing table size for AID registration.
     * @throws  IOException if any exception occurs while retrieving the size.
     */
    public int getMaxAidRoutingTableSize() throws IOException{
        try{
            return sNxpService.getMaxAidRoutingTableSize();
        }catch(RemoteException e){
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0x00;
        }
    }

    /**
     * This api is called by applications to get the size of AID data which is already committed
     * to routing table in NFCC.
     * <p>Requires {@link android.Manifest.permission#NFC} permission.
     * @return  occupied size of routing table for AID registrations.
     * @throws  IOException if any exception occurs while retrieving the size.
     */
    public int getCommittedAidRoutingTableSize() throws IOException{
        try{
            return sNxpService.getCommittedAidRoutingTableSize();
        }catch(RemoteException e){
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0x00;
        }
    }

    /**
     * This api is called by applications to update the service state of card emualation
     * services.
     * <p>This api is implemented for  {@link android.nfc.cardemulation.CardEmulation#CATEGORY_OTHER}.
     * <p>Requires {@link android.Manifest.permission#NFC} permission.<ul>
     * <li>This api should be called only when the intent AID routing
     *     table full is sent by NfcService.
     * <li>The service state change is persistent for particular UserId.
     * <li>The service state is written to the Xml and read
     *     before every routing table  change.
     * <li>If there is any change in routing table  the routing table is updated to NFCC
     *     after calling this api.
     * </ul>
     * @param  serviceState Map of ServiceName and state of service.
     * @return whether  the update of Card Emulation services is
     *          success or not.
     *          0xFF - failure
     *          0x00 - success
     * @throws  IOException if any exception occurs during the service state change.
     */
    public int updateServiceState(Map<String , Boolean> serviceState) throws IOException{
        try {
            return sNxpService.updateServiceState(UserHandle.myUserId() , serviceState);
        }catch(RemoteException e)
        {
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0xFF;
        }
    }

    /**
     * Get the current NFCC firware version.
     * @return 2 byte array with Major ver(0 index) adn Minor ver(1 index)
     */
    public byte[] getFwVersion() throws IOException
    {
        try{
            return sNxpService.getFWVersion();
        }
        catch(RemoteException e)
        {
            Log.e(TAG, "RemoteException in getFwVersion(): ", e);
            attemptDeadServiceRecovery(e);
            throw new IOException("RemoteException in getFwVersion()");
        }
    }

    public byte[] readerPassThruMode(byte status, byte modulationTyp)
        throws IOException {
      try {
        return sNxpService.readerPassThruMode(status, modulationTyp);
      } catch (RemoteException e) {
        Log.e(TAG, "Remote exception in readerPassThruMode(): ", e);
        throw new IOException("Remote exception in readerPassThruMode()");
      }
    }

    public byte[] transceiveAppData(byte[] data) throws IOException {
      try {
        return sNxpService.transceiveAppData(data);
      } catch (RemoteException e) {
        Log.e(TAG, "RemoteException in transceiveAppData(): ", e);
        throw new IOException("RemoteException in transceiveAppData()");
      }
    }
    /**
     * This api is called by applications to update the NFC configurations which are
     * already part of libnfc-nxp.conf and libnfc-brcm.conf
     * <p>Requires {@link android.Manifest.permission#NFC} permission.<ul>
     * <li>This api shall be called only Nfcservice is enabled.
     * <li>This api shall be called only when there are no NFC transactions ongoing
     * </ul>
     * @param  configs NFC Configuration to be updated.
     * @param  pkg package name of the caller
     * @return whether  the update of configuration is
     *          success or not.
     *          0xFF - failure
     *          0x00 - success
     * @throws  IOException if any exception occurs during setting the NFC configuration.
     */
    public int setConfig(String configs , String pkg) throws IOException {
        try {
            return sNxpService.setConfig(configs , pkg);
        } catch(RemoteException e) {
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0xFF;
        }
    }
    /**
     * This api is called by applications to select the UICC slot. Selected Slot
     * will be activated for all type of CE from UICC.
     * <p>Requires {@link android.Manifest.permission#NFC} permission.<ul>
     * <li>This api shall be called only Nfcservice is enabled.
     * </ul>
     * @param  uicc slot number to select
     * @return whether  the update of configuration is
     *          success or not.
     *          0xFF - failure
     *          0x00 - success
     * @throws  IOException if any exception occurs during setting the NFC configuration.
     */
    public int selectUicc(int uiccSlot) throws IOException {
        try {
            return sNxpService.selectUicc(uiccSlot);
        } catch(RemoteException e) {
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0xFF;
        }
    }
    /**
     * This api is called by applications to get Selected UICC slot. Selected Slot
     * will be used for all type of CE from UICC.
     * <p>Requires {@link android.Manifest.permission#NFC} permission.<ul>
     * <li>This api shall be called only Nfcservice is enabled.
     * </ul>
     * @param  uicc slot number to select
     * @return whether  the update of configuration is
     *          success or not.
     *          0xFF - failure
     *          0x00 - success
     * @throws  IOException if any exception occurs during setting the NFC configuration.
     */
    public int getSelectedUicc() throws IOException {
        try {
            return sNxpService.getSelectedUicc();
        } catch(RemoteException e) {
            e.printStackTrace();
            attemptDeadServiceRecovery(e);
            return 0xFF;
        }
    }
}