Home | History | Annotate | Download | only in nfc
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.nfc;
     18 
     19 import com.android.internal.nfc.LlcpServiceSocket;
     20 import com.android.internal.nfc.LlcpSocket;
     21 
     22 import android.app.Application;
     23 import android.content.ActivityNotFoundException;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.SharedPreferences;
     29 import android.nfc.ErrorCodes;
     30 import android.nfc.FormatException;
     31 import android.nfc.ILlcpConnectionlessSocket;
     32 import android.nfc.ILlcpServiceSocket;
     33 import android.nfc.ILlcpSocket;
     34 import android.nfc.INfcAdapter;
     35 import android.nfc.INfcTag;
     36 import android.nfc.IP2pInitiator;
     37 import android.nfc.IP2pTarget;
     38 import android.nfc.LlcpPacket;
     39 import android.nfc.NdefMessage;
     40 import android.nfc.NdefTag;
     41 import android.nfc.NfcAdapter;
     42 import android.nfc.Tag;
     43 import android.os.AsyncTask;
     44 import android.os.Handler;
     45 import android.os.Message;
     46 import android.os.PowerManager;
     47 import android.os.RemoteException;
     48 import android.os.ServiceManager;
     49 import android.util.Log;
     50 
     51 import java.util.HashMap;
     52 import java.util.LinkedList;
     53 import java.util.ListIterator;
     54 
     55 public class NfcService extends Application {
     56     static final boolean DBG = false;
     57 
     58     static {
     59         System.loadLibrary("nfc_jni");
     60     }
     61 
     62     public static final String SERVICE_NAME = "nfc";
     63 
     64     private static final String TAG = "NfcService";
     65 
     66     private static final String NFC_PERM = android.Manifest.permission.NFC;
     67     private static final String NFC_PERM_ERROR = "NFC permission required";
     68     private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
     69     private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
     70 
     71     private static final String PREF = "NfcServicePrefs";
     72 
     73     private static final String PREF_NFC_ON = "nfc_on";
     74     private static final boolean NFC_ON_DEFAULT = true;
     75 
     76     private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
     77     private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
     78 
     79     private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
     80     private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
     81 
     82     private static final String PREF_LLCP_LTO = "llcp_lto";
     83     private static final int LLCP_LTO_DEFAULT = 150;
     84     private static final int LLCP_LTO_MAX = 255;
     85 
     86     /** Maximum Information Unit */
     87     private static final String PREF_LLCP_MIU = "llcp_miu";
     88     private static final int LLCP_MIU_DEFAULT = 128;
     89     private static final int LLCP_MIU_MAX = 2176;
     90 
     91     /** Well Known Service List */
     92     private static final String PREF_LLCP_WKS = "llcp_wks";
     93     private static final int LLCP_WKS_DEFAULT = 1;
     94     private static final int LLCP_WKS_MAX = 15;
     95 
     96     private static final String PREF_LLCP_OPT = "llcp_opt";
     97     private static final int LLCP_OPT_DEFAULT = 0;
     98     private static final int LLCP_OPT_MAX = 3;
     99 
    100     private static final String PREF_DISCOVERY_A = "discovery_a";
    101     private static final boolean DISCOVERY_A_DEFAULT = true;
    102 
    103     private static final String PREF_DISCOVERY_B = "discovery_b";
    104     private static final boolean DISCOVERY_B_DEFAULT = true;
    105 
    106     private static final String PREF_DISCOVERY_F = "discovery_f";
    107     private static final boolean DISCOVERY_F_DEFAULT = true;
    108 
    109     private static final String PREF_DISCOVERY_15693 = "discovery_15693";
    110     private static final boolean DISCOVERY_15693_DEFAULT = true;
    111 
    112     private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
    113     private static final boolean DISCOVERY_NFCIP_DEFAULT = false;
    114 
    115     /** NFC Reader Discovery mode for enableDiscovery() */
    116     private static final int DISCOVERY_MODE_READER = 0;
    117 
    118     /** Card Emulation Discovery mode for enableDiscovery() */
    119     private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
    120 
    121     private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
    122     private static final int LLCP_SOCKET_TYPE = 1;
    123     private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
    124     private static final int LLCP_SOCKET_NB_MAX = 5;  // Maximum number of socket managed
    125     private static final int LLCP_RW_MAX_VALUE = 15;  // Receive Window
    126 
    127     private static final int PROPERTY_LLCP_LTO = 0;
    128     private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
    129     private static final int PROPERTY_LLCP_MIU = 1;
    130     private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
    131     private static final int PROPERTY_LLCP_WKS = 2;
    132     private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
    133     private static final int PROPERTY_LLCP_OPT = 3;
    134     private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
    135     private static final int PROPERTY_NFC_DISCOVERY_A = 4;
    136     private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
    137     private static final int PROPERTY_NFC_DISCOVERY_B = 5;
    138     private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
    139     private static final int PROPERTY_NFC_DISCOVERY_F = 6;
    140     private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
    141     private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
    142     private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
    143     private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
    144     private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
    145 
    146     static final int MSG_NDEF_TAG = 0;
    147     static final int MSG_CARD_EMULATION = 1;
    148     static final int MSG_LLCP_LINK_ACTIVATION = 2;
    149     static final int MSG_LLCP_LINK_DEACTIVATED = 3;
    150     static final int MSG_TARGET_DESELECTED = 4;
    151 
    152     // TODO: none of these appear to be synchronized but are
    153     // read/written from different threads (notably Binder threads)...
    154     private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
    155     private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
    156     private int mGeneratedSocketHandle = 0;
    157     private int mNbSocketCreated = 0;
    158     private volatile boolean mIsNfcEnabled = false;
    159     private int mSelectedSeId = 0;
    160     private boolean mNfcSecureElementState;
    161 
    162     // fields below are used in multiple threads and protected by synchronized(this)
    163     private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
    164     private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
    165     private boolean mScreenOn;
    166 
    167     // fields below are final after onCreate()
    168     private Context mContext;
    169     private NativeNfcManager mManager;
    170     private SharedPreferences mPrefs;
    171     private SharedPreferences.Editor mPrefsEditor;
    172     private PowerManager.WakeLock mWakeLock;
    173 
    174     private static NfcService sService;
    175 
    176     public static NfcService getInstance() {
    177         return sService;
    178     }
    179 
    180     @Override
    181     public void onCreate() {
    182         super.onCreate();
    183 
    184         Log.i(TAG, "Starting NFC service");
    185 
    186         sService = this;
    187 
    188         mContext = this;
    189         mManager = new NativeNfcManager(mContext, this);
    190         mManager.initializeNativeStructure();
    191 
    192         mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    193         mPrefsEditor = mPrefs.edit();
    194 
    195         mIsNfcEnabled = false;  // real preference read later
    196 
    197         PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    198         mScreenOn = pm.isScreenOn();
    199         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
    200 
    201         ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
    202 
    203         IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
    204         filter.addAction(Intent.ACTION_SCREEN_OFF);
    205         filter.addAction(Intent.ACTION_SCREEN_ON);
    206         mContext.registerReceiver(mReceiver, filter);
    207 
    208         Thread t = new Thread() {
    209             @Override
    210             public void run() {
    211                 boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
    212                 if (nfc_on) {
    213                     _enable(false);
    214                 }
    215             }
    216         };
    217         t.start();
    218     }
    219 
    220     @Override
    221     public void onTerminate() {
    222         super.onTerminate();
    223         // NFC application is persistent, it should not be destroyed by framework
    224         Log.wtf(TAG, "NFC service is under attack!");
    225     }
    226 
    227     private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
    228         /** Protected by "this" */
    229         NdefMessage mLocalMessage = null;
    230 
    231         @Override
    232         public boolean enable() throws RemoteException {
    233             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    234 
    235             boolean isSuccess = false;
    236             boolean previouslyEnabled = isEnabled();
    237             if (!previouslyEnabled) {
    238                 reset();
    239                 isSuccess = _enable(previouslyEnabled);
    240             }
    241             return isSuccess;
    242         }
    243 
    244         @Override
    245         public boolean disable() throws RemoteException {
    246             boolean isSuccess = false;
    247             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    248             boolean previouslyEnabled = isEnabled();
    249             if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
    250 
    251             if (previouslyEnabled) {
    252                 /* tear down the my tag server */
    253                 isSuccess = mManager.deinitialize();
    254                 if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
    255                 if (isSuccess) {
    256                     mIsNfcEnabled = false;
    257                 }
    258             }
    259 
    260             updateNfcOnSetting(previouslyEnabled);
    261 
    262             return isSuccess;
    263         }
    264 
    265         @Override
    266         public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
    267             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    268 
    269             // Check if NFC is enabled
    270             if (!mIsNfcEnabled) {
    271                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    272             }
    273 
    274             /* Check SAP is not already used */
    275 
    276             /* Check nb socket created */
    277             if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
    278                 /* Store the socket handle */
    279                 int sockeHandle = mGeneratedSocketHandle;
    280 
    281                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
    282                     NativeLlcpConnectionlessSocket socket;
    283 
    284                     socket = mManager.doCreateLlcpConnectionlessSocket(sap);
    285                     if (socket != null) {
    286                         synchronized(NfcService.this) {
    287                             /* Update the number of socket created */
    288                             mNbSocketCreated++;
    289 
    290                             /* Add the socket into the socket map */
    291                             mSocketMap.put(sockeHandle, socket);
    292                         }
    293                         return sockeHandle;
    294                     } else {
    295                         /*
    296                          * socket creation error - update the socket handle
    297                          * generation
    298                          */
    299                         mGeneratedSocketHandle -= 1;
    300 
    301                         /* Get Error Status */
    302                         int errorStatus = mManager.doGetLastError();
    303 
    304                         switch (errorStatus) {
    305                             case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    306                                 return ErrorCodes.ERROR_BUFFER_TO_SMALL;
    307                             case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    308                                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    309                             default:
    310                                 return ErrorCodes.ERROR_SOCKET_CREATION;
    311                         }
    312                     }
    313                 } else {
    314                     /* Check SAP is not already used */
    315                     if (!CheckSocketSap(sap)) {
    316                         return ErrorCodes.ERROR_SAP_USED;
    317                     }
    318 
    319                     NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
    320 
    321                     synchronized(NfcService.this) {
    322                         /* Add the socket into the socket map */
    323                         mSocketMap.put(sockeHandle, socket);
    324 
    325                         /* Update the number of socket created */
    326                         mNbSocketCreated++;
    327                     }
    328                     /* Create new registered socket */
    329                     RegisteredSocket registeredSocket = new RegisteredSocket(
    330                             LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
    331 
    332                     /* Put this socket into a list of registered socket */
    333                     mRegisteredSocketList.add(registeredSocket);
    334                 }
    335 
    336                 /* update socket handle generation */
    337                 mGeneratedSocketHandle++;
    338 
    339                 return sockeHandle;
    340 
    341             } else {
    342                 /* No socket available */
    343                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    344             }
    345 
    346         }
    347 
    348         @Override
    349         public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
    350                 throws RemoteException {
    351             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    352 
    353             // Check if NFC is enabled
    354             if (!mIsNfcEnabled) {
    355                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    356             }
    357 
    358             if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
    359                 int sockeHandle = mGeneratedSocketHandle;
    360 
    361                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
    362                     NativeLlcpServiceSocket socket;
    363 
    364                     socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
    365                     if (socket != null) {
    366                         synchronized(NfcService.this) {
    367                             /* Update the number of socket created */
    368                             mNbSocketCreated++;
    369                             /* Add the socket into the socket map */
    370                             mSocketMap.put(sockeHandle, socket);
    371                         }
    372                     } else {
    373                         /* socket creation error - update the socket handle counter */
    374                         mGeneratedSocketHandle -= 1;
    375 
    376                         /* Get Error Status */
    377                         int errorStatus = mManager.doGetLastError();
    378 
    379                         switch (errorStatus) {
    380                             case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    381                                 return ErrorCodes.ERROR_BUFFER_TO_SMALL;
    382                             case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    383                                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    384                             default:
    385                                 return ErrorCodes.ERROR_SOCKET_CREATION;
    386                         }
    387                     }
    388                 } else {
    389 
    390                     /* Check SAP is not already used */
    391                     if (!CheckSocketSap(sap)) {
    392                         return ErrorCodes.ERROR_SAP_USED;
    393                     }
    394 
    395                     /* Service Name */
    396                     if (!CheckSocketServiceName(sn)) {
    397                         return ErrorCodes.ERROR_SERVICE_NAME_USED;
    398                     }
    399 
    400                     /* Check socket options */
    401                     if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
    402                         return ErrorCodes.ERROR_SOCKET_OPTIONS;
    403                     }
    404 
    405                     NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw,
    406                             linearBufferLength);
    407                     synchronized(NfcService.this) {
    408                         /* Add the socket into the socket map */
    409                         mSocketMap.put(sockeHandle, socket);
    410 
    411                         /* Update the number of socket created */
    412                         mNbSocketCreated++;
    413                     }
    414                     /* Create new registered socket */
    415                     RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
    416                             sockeHandle, sap, sn, miu, rw, linearBufferLength);
    417 
    418                     /* Put this socket into a list of registered socket */
    419                     mRegisteredSocketList.add(registeredSocket);
    420                 }
    421 
    422                 /* update socket handle generation */
    423                 mGeneratedSocketHandle += 1;
    424 
    425                 if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
    426                 return sockeHandle;
    427             } else {
    428                 /* No socket available */
    429                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    430             }
    431         }
    432 
    433         @Override
    434         public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
    435                 throws RemoteException {
    436             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    437 
    438             // Check if NFC is enabled
    439             if (!mIsNfcEnabled) {
    440                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    441             }
    442 
    443             if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
    444 
    445                 int sockeHandle = mGeneratedSocketHandle;
    446 
    447                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
    448                     if (DBG) Log.d(TAG, "creating llcp socket while activated");
    449                     NativeLlcpSocket socket;
    450 
    451                     socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
    452 
    453                     if (socket != null) {
    454                         synchronized(NfcService.this) {
    455                             /* Update the number of socket created */
    456                             mNbSocketCreated++;
    457                             /* Add the socket into the socket map */
    458                             mSocketMap.put(sockeHandle, socket);
    459                         }
    460                     } else {
    461                         /*
    462                          * socket creation error - update the socket handle
    463                          * generation
    464                          */
    465                         mGeneratedSocketHandle -= 1;
    466 
    467                         /* Get Error Status */
    468                         int errorStatus = mManager.doGetLastError();
    469 
    470                         Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
    471 
    472                         switch (errorStatus) {
    473                             case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    474                                 return ErrorCodes.ERROR_BUFFER_TO_SMALL;
    475                             case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    476                                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    477                             default:
    478                                 return ErrorCodes.ERROR_SOCKET_CREATION;
    479                         }
    480                     }
    481                 } else {
    482                     if (DBG) Log.d(TAG, "registering llcp socket while not activated");
    483 
    484                     /* Check SAP is not already used */
    485                     if (!CheckSocketSap(sap)) {
    486                         return ErrorCodes.ERROR_SAP_USED;
    487                     }
    488 
    489                     /* Check Socket options */
    490                     if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
    491                         return ErrorCodes.ERROR_SOCKET_OPTIONS;
    492                     }
    493 
    494                     NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
    495                     synchronized(NfcService.this) {
    496                         /* Add the socket into the socket map */
    497                         mSocketMap.put(sockeHandle, socket);
    498 
    499                         /* Update the number of socket created */
    500                         mNbSocketCreated++;
    501                     }
    502                     /* Create new registered socket */
    503                     RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
    504                             sockeHandle, sap, miu, rw, linearBufferLength);
    505 
    506                     /* Put this socket into a list of registered socket */
    507                     mRegisteredSocketList.add(registeredSocket);
    508                 }
    509 
    510                 /* update socket handle generation */
    511                 mGeneratedSocketHandle++;
    512 
    513                 return sockeHandle;
    514             } else {
    515                 /* No socket available */
    516                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
    517             }
    518         }
    519 
    520         @Override
    521         public int deselectSecureElement() throws RemoteException {
    522             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    523 
    524             // Check if NFC is enabled
    525             if (!mIsNfcEnabled) {
    526                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    527             }
    528 
    529             if (mSelectedSeId == 0) {
    530                 return ErrorCodes.ERROR_NO_SE_CONNECTED;
    531             }
    532 
    533             mManager.doDeselectSecureElement(mSelectedSeId);
    534             mNfcSecureElementState = false;
    535             mSelectedSeId = 0;
    536 
    537             /* store preference */
    538             mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
    539             mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
    540             mPrefsEditor.apply();
    541 
    542             return ErrorCodes.SUCCESS;
    543         }
    544 
    545         @Override
    546         public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
    547             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    548             return mLlcpConnectionlessSocketService;
    549         }
    550 
    551         @Override
    552         public ILlcpSocket getLlcpInterface() throws RemoteException {
    553             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    554             return mLlcpSocket;
    555         }
    556 
    557         @Override
    558         public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
    559             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    560             return mLlcpServerSocketService;
    561         }
    562 
    563         @Override
    564         public INfcTag getNfcTagInterface() throws RemoteException {
    565             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    566             return mNfcTagService;
    567         }
    568 
    569         @Override
    570         public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
    571             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    572             return mP2pInitiatorService;
    573         }
    574 
    575         @Override
    576         public IP2pTarget getP2pTargetInterface() throws RemoteException {
    577             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    578             return mP2pTargetService;
    579         }
    580 
    581         @Override
    582         public String getProperties(String param) throws RemoteException {
    583             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    584 
    585             if (param == null) {
    586                 return null;
    587             }
    588 
    589             if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
    590                 return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
    591             } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
    592                 return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
    593             } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
    594                 return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
    595             } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
    596                 return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
    597             } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
    598                 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
    599             } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
    600                 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
    601             } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
    602                 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
    603             } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
    604                 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
    605             } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
    606                 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
    607             } else {
    608                 return "Unknown property";
    609             }
    610         }
    611 
    612         @Override
    613         public int[] getSecureElementList() throws RemoteException {
    614             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    615 
    616             int[] list = null;
    617             if (mIsNfcEnabled == true) {
    618                 list = mManager.doGetSecureElementList();
    619             }
    620             return list;
    621         }
    622 
    623         @Override
    624         public int getSelectedSecureElement() throws RemoteException {
    625             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    626 
    627             return mSelectedSeId;
    628         }
    629 
    630         @Override
    631         public boolean isEnabled() throws RemoteException {
    632             return mIsNfcEnabled;
    633         }
    634 
    635         @Override
    636         public void openTagConnection(Tag tag) throws RemoteException {
    637             // TODO: Remove obsolete code
    638         }
    639 
    640         @Override
    641         public int selectSecureElement(int seId) throws RemoteException {
    642             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    643 
    644             // Check if NFC is enabled
    645             if (!mIsNfcEnabled) {
    646                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    647             }
    648 
    649             if (mSelectedSeId == seId) {
    650                 return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
    651             }
    652 
    653             if (mSelectedSeId != 0) {
    654                 return ErrorCodes.ERROR_SE_CONNECTED;
    655             }
    656 
    657             mSelectedSeId = seId;
    658             mManager.doSelectSecureElement(mSelectedSeId);
    659 
    660             /* store */
    661             mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
    662             mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
    663             mPrefsEditor.apply();
    664 
    665             mNfcSecureElementState = true;
    666 
    667             return ErrorCodes.SUCCESS;
    668 
    669         }
    670 
    671         @Override
    672         public int setProperties(String param, String value) throws RemoteException {
    673             mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    674 
    675             if (isEnabled()) {
    676                 return ErrorCodes.ERROR_NFC_ON;
    677             }
    678 
    679             int val;
    680 
    681             /* Check params validity */
    682             if (param == null || value == null) {
    683                 return ErrorCodes.ERROR_INVALID_PARAM;
    684             }
    685 
    686             if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
    687                 val = Integer.parseInt(value);
    688 
    689                 /* Check params */
    690                 if (val > LLCP_LTO_MAX)
    691                     return ErrorCodes.ERROR_INVALID_PARAM;
    692 
    693                 /* Store value */
    694                 mPrefsEditor.putInt(PREF_LLCP_LTO, val);
    695                 mPrefsEditor.apply();
    696 
    697                 /* Update JNI */
    698                 mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
    699 
    700             } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
    701                 val = Integer.parseInt(value);
    702 
    703                 /* Check params */
    704                 if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
    705                     return ErrorCodes.ERROR_INVALID_PARAM;
    706 
    707                 /* Store value */
    708                 mPrefsEditor.putInt(PREF_LLCP_MIU, val);
    709                 mPrefsEditor.apply();
    710 
    711                 /* Update JNI */
    712                 mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
    713 
    714             } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
    715                 val = Integer.parseInt(value);
    716 
    717                 /* Check params */
    718                 if (val > LLCP_WKS_MAX)
    719                     return ErrorCodes.ERROR_INVALID_PARAM;
    720 
    721                 /* Store value */
    722                 mPrefsEditor.putInt(PREF_LLCP_WKS, val);
    723                 mPrefsEditor.apply();
    724 
    725                 /* Update JNI */
    726                 mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
    727 
    728             } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
    729                 val = Integer.parseInt(value);
    730 
    731                 /* Check params */
    732                 if (val > LLCP_OPT_MAX)
    733                     return ErrorCodes.ERROR_INVALID_PARAM;
    734 
    735                 /* Store value */
    736                 mPrefsEditor.putInt(PREF_LLCP_OPT, val);
    737                 mPrefsEditor.apply();
    738 
    739                 /* Update JNI */
    740                 mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
    741 
    742             } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
    743                 boolean b = Boolean.parseBoolean(value);
    744 
    745                 /* Store value */
    746                 mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
    747                 mPrefsEditor.apply();
    748 
    749                 /* Update JNI */
    750                 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
    751 
    752             } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
    753                 boolean b = Boolean.parseBoolean(value);
    754 
    755                 /* Store value */
    756                 mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
    757                 mPrefsEditor.apply();
    758 
    759                 /* Update JNI */
    760                 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
    761 
    762             } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
    763                 boolean b = Boolean.parseBoolean(value);
    764 
    765                 /* Store value */
    766                 mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
    767                 mPrefsEditor.apply();
    768 
    769                 /* Update JNI */
    770                 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
    771 
    772             } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
    773                 boolean b = Boolean.parseBoolean(value);
    774 
    775                 /* Store value */
    776                 mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
    777                 mPrefsEditor.apply();
    778 
    779                 /* Update JNI */
    780                 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
    781 
    782             } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
    783                 boolean b = Boolean.parseBoolean(value);
    784 
    785                 /* Store value */
    786                 mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
    787                 mPrefsEditor.apply();
    788 
    789                 /* Update JNI */
    790                 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
    791 
    792             } else {
    793                 return ErrorCodes.ERROR_INVALID_PARAM;
    794             }
    795 
    796             return ErrorCodes.SUCCESS;
    797         }
    798     };
    799 
    800     private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
    801 
    802         private final int CONNECT_FLAG = 0x01;
    803         private final int CLOSE_FLAG   = 0x02;
    804         private final int RECV_FLAG    = 0x04;
    805         private final int SEND_FLAG    = 0x08;
    806 
    807         private int concurrencyFlags;
    808         private Object sync;
    809 
    810         @Override
    811         public int close(int nativeHandle) throws RemoteException {
    812             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    813 
    814             NativeLlcpSocket socket = null;
    815             boolean isSuccess = false;
    816 
    817             // Check if NFC is enabled
    818             if (!mIsNfcEnabled) {
    819                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    820             }
    821 
    822             /* find the socket in the hmap */
    823             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    824             if (socket != null) {
    825                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
    826                     isSuccess = socket.doClose();
    827                     if (isSuccess) {
    828                         /* Remove the socket closed from the hmap */
    829                         RemoveSocket(nativeHandle);
    830                         /* Update mNbSocketCreated */
    831                         mNbSocketCreated--;
    832                         return ErrorCodes.SUCCESS;
    833                     } else {
    834                         return ErrorCodes.ERROR_IO;
    835                     }
    836                 } else {
    837                     /* Remove the socket closed from the hmap */
    838                     RemoveSocket(nativeHandle);
    839 
    840                     /* Remove registered socket from the list */
    841                     RemoveRegisteredSocket(nativeHandle);
    842 
    843                     /* Update mNbSocketCreated */
    844                     mNbSocketCreated--;
    845 
    846                     return ErrorCodes.SUCCESS;
    847                 }
    848             } else {
    849                 return ErrorCodes.ERROR_IO;
    850             }
    851         }
    852 
    853         @Override
    854         public int connect(int nativeHandle, int sap) throws RemoteException {
    855             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    856 
    857             NativeLlcpSocket socket = null;
    858             boolean isSuccess = false;
    859 
    860             // Check if NFC is enabled
    861             if (!mIsNfcEnabled) {
    862                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    863             }
    864 
    865             /* find the socket in the hmap */
    866             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    867             if (socket != null) {
    868                 isSuccess = socket.doConnect(sap);
    869                 if (isSuccess) {
    870                     return ErrorCodes.SUCCESS;
    871                 } else {
    872                     return ErrorCodes.ERROR_IO;
    873                 }
    874             } else {
    875                 return ErrorCodes.ERROR_IO;
    876             }
    877 
    878         }
    879 
    880         @Override
    881         public int connectByName(int nativeHandle, String sn) throws RemoteException {
    882             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    883 
    884             NativeLlcpSocket socket = null;
    885             boolean isSuccess = false;
    886 
    887             // Check if NFC is enabled
    888             if (!mIsNfcEnabled) {
    889                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    890             }
    891 
    892             /* find the socket in the hmap */
    893             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    894             if (socket != null) {
    895                 isSuccess = socket.doConnectBy(sn);
    896                 if (isSuccess) {
    897                     return ErrorCodes.SUCCESS;
    898                 } else {
    899                     return ErrorCodes.ERROR_IO;
    900                 }
    901             } else {
    902                 return ErrorCodes.ERROR_IO;
    903             }
    904 
    905         }
    906 
    907         @Override
    908         public int getLocalSap(int nativeHandle) throws RemoteException {
    909             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    910 
    911             NativeLlcpSocket socket = null;
    912 
    913             // Check if NFC is enabled
    914             if (!mIsNfcEnabled) {
    915                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    916             }
    917 
    918             /* find the socket in the hmap */
    919             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    920             if (socket != null) {
    921                 return socket.getSap();
    922             } else {
    923                 return 0;
    924             }
    925         }
    926 
    927         @Override
    928         public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
    929             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    930 
    931             NativeLlcpSocket socket = null;
    932 
    933             // Check if NFC is enabled
    934             if (!mIsNfcEnabled) {
    935                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    936             }
    937 
    938             /* find the socket in the hmap */
    939             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    940             if (socket != null) {
    941                 return socket.getMiu();
    942             } else {
    943                 return 0;
    944             }
    945         }
    946 
    947         @Override
    948         public int getLocalSocketRw(int nativeHandle) throws RemoteException {
    949             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    950 
    951             NativeLlcpSocket socket = null;
    952 
    953             // Check if NFC is enabled
    954             if (!mIsNfcEnabled) {
    955                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    956             }
    957 
    958             /* find the socket in the hmap */
    959             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    960             if (socket != null) {
    961                 return socket.getRw();
    962             } else {
    963                 return 0;
    964             }
    965         }
    966 
    967         @Override
    968         public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
    969             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    970 
    971             NativeLlcpSocket socket = null;
    972 
    973             // Check if NFC is enabled
    974             if (!mIsNfcEnabled) {
    975                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    976             }
    977 
    978             /* find the socket in the hmap */
    979             socket = (NativeLlcpSocket) findSocket(nativeHandle);
    980             if (socket != null) {
    981                 if (socket.doGetRemoteSocketMiu() != 0) {
    982                     return socket.doGetRemoteSocketMiu();
    983                 } else {
    984                     return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
    985                 }
    986             } else {
    987                 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
    988             }
    989         }
    990 
    991         @Override
    992         public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
    993             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    994 
    995             NativeLlcpSocket socket = null;
    996 
    997             // Check if NFC is enabled
    998             if (!mIsNfcEnabled) {
    999                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1000             }
   1001 
   1002             /* find the socket in the hmap */
   1003             socket = (NativeLlcpSocket) findSocket(nativeHandle);
   1004             if (socket != null) {
   1005                 if (socket.doGetRemoteSocketRw() != 0) {
   1006                     return socket.doGetRemoteSocketRw();
   1007                 } else {
   1008                     return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
   1009                 }
   1010             } else {
   1011                 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
   1012             }
   1013         }
   1014 
   1015         @Override
   1016         public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
   1017             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1018 
   1019             NativeLlcpSocket socket = null;
   1020             int receiveLength = 0;
   1021 
   1022             // Check if NFC is enabled
   1023             if (!mIsNfcEnabled) {
   1024                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1025             }
   1026 
   1027             /* find the socket in the hmap */
   1028             socket = (NativeLlcpSocket) findSocket(nativeHandle);
   1029             if (socket != null) {
   1030                 receiveLength = socket.doReceive(receiveBuffer);
   1031                 if (receiveLength != 0) {
   1032                     return receiveLength;
   1033                 } else {
   1034                     return ErrorCodes.ERROR_IO;
   1035                 }
   1036             } else {
   1037                 return ErrorCodes.ERROR_IO;
   1038             }
   1039         }
   1040 
   1041         @Override
   1042         public int send(int nativeHandle, byte[] data) throws RemoteException {
   1043             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1044 
   1045             NativeLlcpSocket socket = null;
   1046             boolean isSuccess = false;
   1047 
   1048             // Check if NFC is enabled
   1049             if (!mIsNfcEnabled) {
   1050                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1051             }
   1052 
   1053             /* find the socket in the hmap */
   1054             socket = (NativeLlcpSocket) findSocket(nativeHandle);
   1055             if (socket != null) {
   1056                 isSuccess = socket.doSend(data);
   1057                 if (isSuccess) {
   1058                     return ErrorCodes.SUCCESS;
   1059                 } else {
   1060                     return ErrorCodes.ERROR_IO;
   1061                 }
   1062             } else {
   1063                 return ErrorCodes.ERROR_IO;
   1064             }
   1065         }
   1066     };
   1067 
   1068     private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
   1069 
   1070         @Override
   1071         public int accept(int nativeHandle) throws RemoteException {
   1072             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1073 
   1074             NativeLlcpServiceSocket socket = null;
   1075             NativeLlcpSocket clientSocket = null;
   1076 
   1077             // Check if NFC is enabled
   1078             if (!mIsNfcEnabled) {
   1079                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1080             }
   1081 
   1082             if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
   1083                 /* find the socket in the hmap */
   1084                 socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
   1085                 if (socket != null) {
   1086                     clientSocket = socket.doAccept(socket.getMiu(),
   1087                             socket.getRw(), socket.getLinearBufferLength());
   1088                     if (clientSocket != null) {
   1089                         /* Add the socket into the socket map */
   1090                         synchronized(this) {
   1091                             mSocketMap.put(clientSocket.getHandle(), clientSocket);
   1092                             mNbSocketCreated++;
   1093                         }
   1094                         return clientSocket.getHandle();
   1095                     } else {
   1096                         return ErrorCodes.ERROR_IO;
   1097                     }
   1098                 } else {
   1099                     return ErrorCodes.ERROR_IO;
   1100                 }
   1101             } else {
   1102                 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
   1103             }
   1104 
   1105         }
   1106 
   1107         @Override
   1108         public void close(int nativeHandle) throws RemoteException {
   1109             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1110 
   1111             NativeLlcpServiceSocket socket = null;
   1112             boolean isSuccess = false;
   1113 
   1114             // Check if NFC is enabled
   1115             if (!mIsNfcEnabled) {
   1116                 return;
   1117             }
   1118 
   1119             /* find the socket in the hmap */
   1120             boolean closed = false;
   1121             socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
   1122             if (socket != null) {
   1123                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
   1124                     isSuccess = socket.doClose();
   1125                     if (isSuccess) {
   1126                         closed = true;
   1127                     }
   1128                 } else {
   1129                     closed = true;
   1130                 }
   1131             }
   1132 
   1133             // If the socket is closed remove it from the socket lists
   1134             if (closed) {
   1135                 synchronized (this) {
   1136                     /* Remove the socket closed from the hmap */
   1137                     RemoveSocket(nativeHandle);
   1138 
   1139                     /* Update mNbSocketCreated */
   1140                     mNbSocketCreated--;
   1141 
   1142                     /* Remove registered socket from the list */
   1143                     RemoveRegisteredSocket(nativeHandle);
   1144                 }
   1145             }
   1146         }
   1147     };
   1148 
   1149     private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
   1150 
   1151         @Override
   1152         public void close(int nativeHandle) throws RemoteException {
   1153             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1154 
   1155             NativeLlcpConnectionlessSocket socket = null;
   1156             boolean isSuccess = false;
   1157 
   1158             // Check if NFC is enabled
   1159             if (!mIsNfcEnabled) {
   1160                 return;
   1161             }
   1162 
   1163             /* find the socket in the hmap */
   1164             socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
   1165             if (socket != null) {
   1166                 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
   1167                     isSuccess = socket.doClose();
   1168                     if (isSuccess) {
   1169                         /* Remove the socket closed from the hmap */
   1170                         RemoveSocket(nativeHandle);
   1171                         /* Update mNbSocketCreated */
   1172                         mNbSocketCreated--;
   1173                     }
   1174                 } else {
   1175                     /* Remove the socket closed from the hmap */
   1176                     RemoveSocket(nativeHandle);
   1177 
   1178                     /* Remove registered socket from the list */
   1179                     RemoveRegisteredSocket(nativeHandle);
   1180 
   1181                     /* Update mNbSocketCreated */
   1182                     mNbSocketCreated--;
   1183                 }
   1184             }
   1185         }
   1186 
   1187         @Override
   1188         public int getSap(int nativeHandle) throws RemoteException {
   1189             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1190 
   1191             NativeLlcpConnectionlessSocket socket = null;
   1192 
   1193             // Check if NFC is enabled
   1194             if (!mIsNfcEnabled) {
   1195                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1196             }
   1197 
   1198             /* find the socket in the hmap */
   1199             socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
   1200             if (socket != null) {
   1201                 return socket.getSap();
   1202             } else {
   1203                 return 0;
   1204             }
   1205         }
   1206 
   1207         @Override
   1208         public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
   1209             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1210 
   1211             NativeLlcpConnectionlessSocket socket = null;
   1212             LlcpPacket packet;
   1213 
   1214             // Check if NFC is enabled
   1215             if (!mIsNfcEnabled) {
   1216                 return null;
   1217             }
   1218 
   1219             /* find the socket in the hmap */
   1220             socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
   1221             if (socket != null) {
   1222                 packet = socket.doReceiveFrom(socket.getLinkMiu());
   1223                 if (packet != null) {
   1224                     return packet;
   1225                 }
   1226                 return null;
   1227             } else {
   1228                 return null;
   1229             }
   1230         }
   1231 
   1232         @Override
   1233         public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
   1234             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1235 
   1236             NativeLlcpConnectionlessSocket socket = null;
   1237             boolean isSuccess = false;
   1238 
   1239             // Check if NFC is enabled
   1240             if (!mIsNfcEnabled) {
   1241                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1242             }
   1243 
   1244             /* find the socket in the hmap */
   1245             socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
   1246             if (socket != null) {
   1247                 isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
   1248                 if (isSuccess) {
   1249                     return ErrorCodes.SUCCESS;
   1250                 } else {
   1251                     return ErrorCodes.ERROR_IO;
   1252                 }
   1253             } else {
   1254                 return ErrorCodes.ERROR_IO;
   1255             }
   1256         }
   1257     };
   1258 
   1259     private final INfcTag mNfcTagService = new INfcTag.Stub() {
   1260 
   1261         @Override
   1262         public int close(int nativeHandle) throws RemoteException {
   1263             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1264 
   1265             NativeNfcTag tag = null;
   1266 
   1267             // Check if NFC is enabled
   1268             if (!mIsNfcEnabled) {
   1269                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1270             }
   1271 
   1272             /* find the tag in the hmap */
   1273             tag = (NativeNfcTag) findObject(nativeHandle);
   1274             if (tag != null) {
   1275                 /* Remove the device from the hmap */
   1276                 unregisterObject(nativeHandle);
   1277                 tag.disconnect();
   1278                 return ErrorCodes.SUCCESS;
   1279             }
   1280             /* Restart polling loop for notification */
   1281             maybeEnableDiscovery();
   1282             return ErrorCodes.ERROR_DISCONNECT;
   1283         }
   1284 
   1285         @Override
   1286         public int connect(int nativeHandle) throws RemoteException {
   1287             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1288 
   1289             NativeNfcTag tag = null;
   1290 
   1291             // Check if NFC is enabled
   1292             if (!mIsNfcEnabled) {
   1293                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1294             }
   1295 
   1296             /* find the tag in the hmap */
   1297             tag = (NativeNfcTag) findObject(nativeHandle);
   1298             if (tag == null) {
   1299                 return ErrorCodes.ERROR_DISCONNECT;
   1300             }
   1301             // TODO: register the tag as being locked rather than really connect
   1302             return ErrorCodes.SUCCESS;
   1303         }
   1304 
   1305         @Override
   1306         public String getType(int nativeHandle) throws RemoteException {
   1307             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1308 
   1309             NativeNfcTag tag = null;
   1310             String type;
   1311 
   1312             // Check if NFC is enabled
   1313             if (!mIsNfcEnabled) {
   1314                 return null;
   1315             }
   1316 
   1317             /* find the tag in the hmap */
   1318             tag = (NativeNfcTag) findObject(nativeHandle);
   1319             if (tag != null) {
   1320                 type = tag.getType();
   1321                 return type;
   1322             }
   1323             return null;
   1324         }
   1325 
   1326         @Override
   1327         public byte[] getUid(int nativeHandle) throws RemoteException {
   1328             NativeNfcTag tag = null;
   1329             byte[] uid;
   1330 
   1331             // Check if NFC is enabled
   1332             if (!mIsNfcEnabled) {
   1333                 return null;
   1334             }
   1335 
   1336             /* find the tag in the hmap */
   1337             tag = (NativeNfcTag) findObject(nativeHandle);
   1338             if (tag != null) {
   1339                 uid = tag.getUid();
   1340                 return uid;
   1341             }
   1342             return null;
   1343         }
   1344 
   1345         @Override
   1346         public boolean isPresent(int nativeHandle) throws RemoteException {
   1347             NativeNfcTag tag = null;
   1348 
   1349             // Check if NFC is enabled
   1350             if (!mIsNfcEnabled) {
   1351                 return false;
   1352             }
   1353 
   1354             /* find the tag in the hmap */
   1355             tag = (NativeNfcTag) findObject(nativeHandle);
   1356             if (tag == null) {
   1357                 return false;
   1358             }
   1359 
   1360             return tag.presenceCheck();
   1361         }
   1362 
   1363         @Override
   1364         public boolean isNdef(int nativeHandle) throws RemoteException {
   1365             NativeNfcTag tag = null;
   1366             boolean isSuccess = false;
   1367 
   1368             // Check if NFC is enabled
   1369             if (!mIsNfcEnabled) {
   1370                 return isSuccess;
   1371             }
   1372 
   1373             /* find the tag in the hmap */
   1374             tag = (NativeNfcTag) findObject(nativeHandle);
   1375             if (tag != null) {
   1376                 isSuccess = tag.checkNdef();
   1377             }
   1378             return isSuccess;
   1379         }
   1380 
   1381         @Override
   1382         public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException {
   1383             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1384 
   1385             NativeNfcTag tag = null;
   1386             byte[] response;
   1387 
   1388             // Check if NFC is enabled
   1389             if (!mIsNfcEnabled) {
   1390                 return null;
   1391             }
   1392 
   1393             /* find the tag in the hmap */
   1394             tag = (NativeNfcTag) findObject(nativeHandle);
   1395             if (tag != null) {
   1396                 response = tag.transceive(data);
   1397                 return response;
   1398             }
   1399             return null;
   1400         }
   1401 
   1402         @Override
   1403         public NdefMessage read(int nativeHandle) throws RemoteException {
   1404             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1405 
   1406             NativeNfcTag tag;
   1407 
   1408             // Check if NFC is enabled
   1409             if (!mIsNfcEnabled) {
   1410                 return null;
   1411             }
   1412 
   1413             /* find the tag in the hmap */
   1414             tag = (NativeNfcTag) findObject(nativeHandle);
   1415             if (tag != null) {
   1416                 byte[] buf = tag.read();
   1417                 if (buf == null)
   1418                     return null;
   1419 
   1420                 /* Create an NdefMessage */
   1421                 try {
   1422                     return new NdefMessage(buf);
   1423                 } catch (FormatException e) {
   1424                     return null;
   1425                 }
   1426             }
   1427             return null;
   1428         }
   1429 
   1430         @Override
   1431         public int write(int nativeHandle, NdefMessage msg) throws RemoteException {
   1432             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1433 
   1434             NativeNfcTag tag;
   1435 
   1436             // Check if NFC is enabled
   1437             if (!mIsNfcEnabled) {
   1438                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1439             }
   1440 
   1441             /* find the tag in the hmap */
   1442             tag = (NativeNfcTag) findObject(nativeHandle);
   1443             if (tag == null) {
   1444                 return ErrorCodes.ERROR_IO;
   1445             }
   1446 
   1447             if (tag.write(msg.toByteArray())) {
   1448                 return ErrorCodes.SUCCESS;
   1449             }
   1450             else {
   1451                 return ErrorCodes.ERROR_IO;
   1452             }
   1453 
   1454         }
   1455 
   1456         @Override
   1457         public int getLastError(int nativeHandle) throws RemoteException {
   1458             // TODO Auto-generated method stub
   1459             return 0;
   1460         }
   1461 
   1462         @Override
   1463         public int getModeHint(int nativeHandle) throws RemoteException {
   1464             // TODO Auto-generated method stub
   1465             return 0;
   1466         }
   1467 
   1468         @Override
   1469         public int makeReadOnly(int nativeHandle) throws RemoteException {
   1470             // TODO Auto-generated method stub
   1471             return 0;
   1472         }
   1473 
   1474 
   1475     };
   1476 
   1477     private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
   1478 
   1479         @Override
   1480         public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
   1481             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1482 
   1483             NativeP2pDevice device;
   1484 
   1485             // Check if NFC is enabled
   1486             if (!mIsNfcEnabled) {
   1487                 return null;
   1488             }
   1489 
   1490             /* find the device in the hmap */
   1491             device = (NativeP2pDevice) findObject(nativeHandle);
   1492             if (device != null) {
   1493                 byte[] buff = device.getGeneralBytes();
   1494                 if (buff == null)
   1495                     return null;
   1496                 return buff;
   1497             }
   1498             return null;
   1499         }
   1500 
   1501         @Override
   1502         public int getMode(int nativeHandle) throws RemoteException {
   1503             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1504 
   1505             NativeP2pDevice device;
   1506 
   1507             // Check if NFC is enabled
   1508             if (!mIsNfcEnabled) {
   1509                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1510             }
   1511 
   1512             /* find the device in the hmap */
   1513             device = (NativeP2pDevice) findObject(nativeHandle);
   1514             if (device != null) {
   1515                 return device.getMode();
   1516             }
   1517             return ErrorCodes.ERROR_INVALID_PARAM;
   1518         }
   1519 
   1520         @Override
   1521         public byte[] receive(int nativeHandle) throws RemoteException {
   1522             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1523 
   1524             NativeP2pDevice device;
   1525 
   1526             // Check if NFC is enabled
   1527             if (!mIsNfcEnabled) {
   1528                 return null;
   1529             }
   1530 
   1531             /* find the device in the hmap */
   1532             device = (NativeP2pDevice) findObject(nativeHandle);
   1533             if (device != null) {
   1534                 byte[] buff = device.doReceive();
   1535                 if (buff == null)
   1536                     return null;
   1537                 return buff;
   1538             }
   1539             /* Restart polling loop for notification */
   1540             maybeEnableDiscovery();
   1541             return null;
   1542         }
   1543 
   1544         @Override
   1545         public boolean send(int nativeHandle, byte[] data) throws RemoteException {
   1546             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1547 
   1548             NativeP2pDevice device;
   1549             boolean isSuccess = false;
   1550 
   1551             // Check if NFC is enabled
   1552             if (!mIsNfcEnabled) {
   1553                 return isSuccess;
   1554             }
   1555 
   1556             /* find the device in the hmap */
   1557             device = (NativeP2pDevice) findObject(nativeHandle);
   1558             if (device != null) {
   1559                 isSuccess = device.doSend(data);
   1560             }
   1561             return isSuccess;
   1562         }
   1563     };
   1564 
   1565     private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
   1566 
   1567         @Override
   1568         public int connect(int nativeHandle) throws RemoteException {
   1569             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1570 
   1571             NativeP2pDevice device;
   1572 
   1573             // Check if NFC is enabled
   1574             if (!mIsNfcEnabled) {
   1575                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1576             }
   1577 
   1578             /* find the device in the hmap */
   1579             device = (NativeP2pDevice) findObject(nativeHandle);
   1580             if (device != null) {
   1581                 if (device.doConnect()) {
   1582                     return ErrorCodes.SUCCESS;
   1583                 }
   1584             }
   1585             return ErrorCodes.ERROR_CONNECT;
   1586         }
   1587 
   1588         @Override
   1589         public boolean disconnect(int nativeHandle) throws RemoteException {
   1590             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1591 
   1592             NativeP2pDevice device;
   1593             boolean isSuccess = false;
   1594 
   1595             // Check if NFC is enabled
   1596             if (!mIsNfcEnabled) {
   1597                 return isSuccess;
   1598             }
   1599 
   1600             /* find the device in the hmap */
   1601             device = (NativeP2pDevice) findObject(nativeHandle);
   1602             if (device != null) {
   1603                 if (isSuccess = device.doDisconnect()) {
   1604                     /* remove the device from the hmap */
   1605                     unregisterObject(nativeHandle);
   1606                     /* Restart polling loop for notification */
   1607                     maybeEnableDiscovery();
   1608                 }
   1609             }
   1610             return isSuccess;
   1611 
   1612         }
   1613 
   1614         @Override
   1615         public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
   1616             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1617 
   1618             NativeP2pDevice device;
   1619 
   1620             // Check if NFC is enabled
   1621             if (!mIsNfcEnabled) {
   1622                 return null;
   1623             }
   1624 
   1625             /* find the device in the hmap */
   1626             device = (NativeP2pDevice) findObject(nativeHandle);
   1627             if (device != null) {
   1628                 byte[] buff = device.getGeneralBytes();
   1629                 if (buff == null)
   1630                     return null;
   1631                 return buff;
   1632             }
   1633             return null;
   1634         }
   1635 
   1636         @Override
   1637         public int getMode(int nativeHandle) throws RemoteException {
   1638             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1639 
   1640             NativeP2pDevice device;
   1641 
   1642             // Check if NFC is enabled
   1643             if (!mIsNfcEnabled) {
   1644                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1645             }
   1646 
   1647             /* find the device in the hmap */
   1648             device = (NativeP2pDevice) findObject(nativeHandle);
   1649             if (device != null) {
   1650                 return device.getMode();
   1651             }
   1652             return ErrorCodes.ERROR_INVALID_PARAM;
   1653         }
   1654 
   1655         @Override
   1656         public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException {
   1657             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1658 
   1659             NativeP2pDevice device;
   1660 
   1661             // Check if NFC is enabled
   1662             if (!mIsNfcEnabled) {
   1663                 return null;
   1664             }
   1665 
   1666             /* find the device in the hmap */
   1667             device = (NativeP2pDevice) findObject(nativeHandle);
   1668             if (device != null) {
   1669                 byte[] buff = device.doTransceive(data);
   1670                 if (buff == null)
   1671                     return null;
   1672                 return buff;
   1673             }
   1674             return null;
   1675         }
   1676     };
   1677 
   1678     private boolean _enable(boolean oldEnabledState) {
   1679         boolean isSuccess = mManager.initialize();
   1680         if (isSuccess) {
   1681             applyProperties();
   1682 
   1683             /* Check Secure Element setting */
   1684             mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
   1685                     SECURE_ELEMENT_ON_DEFAULT);
   1686 
   1687             if (mNfcSecureElementState) {
   1688                 int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
   1689                         SECURE_ELEMENT_ID_DEFAULT);
   1690                 int[] Se_list = mManager.doGetSecureElementList();
   1691                 if (Se_list != null) {
   1692                     for (int i = 0; i < Se_list.length; i++) {
   1693                         if (Se_list[i] == secureElementId) {
   1694                             mManager.doSelectSecureElement(Se_list[i]);
   1695                             mSelectedSeId = Se_list[i];
   1696                             break;
   1697                         }
   1698                     }
   1699                 }
   1700             }
   1701 
   1702             mIsNfcEnabled = true;
   1703 
   1704             /* Start polling loop */
   1705             maybeEnableDiscovery();
   1706         } else {
   1707             mIsNfcEnabled = false;
   1708         }
   1709 
   1710         updateNfcOnSetting(oldEnabledState);
   1711 
   1712         return isSuccess;
   1713     }
   1714 
   1715     /** Enable active tag discovery if screen is on and NFC is enabled */
   1716     private synchronized void maybeEnableDiscovery() {
   1717         if (mScreenOn && mIsNfcEnabled) {
   1718             mManager.enableDiscovery(DISCOVERY_MODE_READER);
   1719         }
   1720     }
   1721 
   1722     /** Disable active tag discovery if necessary */
   1723     private synchronized void maybeDisableDiscovery() {
   1724         if (mIsNfcEnabled) {
   1725             mManager.disableDiscovery();
   1726         }
   1727     }
   1728 
   1729     private void applyProperties() {
   1730         mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
   1731         mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
   1732         mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
   1733         mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
   1734         mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
   1735                 mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
   1736         mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
   1737                 mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
   1738         mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
   1739                 mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
   1740         mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
   1741                 mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
   1742         mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
   1743                 mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
   1744      }
   1745 
   1746     private void updateNfcOnSetting(boolean oldEnabledState) {
   1747         int state;
   1748 
   1749         mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
   1750         mPrefsEditor.apply();
   1751 
   1752         synchronized(this) {
   1753             if (oldEnabledState != mIsNfcEnabled) {
   1754                 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
   1755                 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
   1756                 intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
   1757                 mContext.sendBroadcast(intent);
   1758             }
   1759         }
   1760     }
   1761 
   1762     // Reset all internals
   1763     private synchronized void reset() {
   1764         // TODO: none of these appear to be synchronized but are
   1765         // read/written from different threads (notably Binder threads)...
   1766 
   1767         // Clear tables
   1768         mObjectMap.clear();
   1769         mSocketMap.clear();
   1770         mRegisteredSocketList.clear();
   1771 
   1772         // Reset variables
   1773         mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
   1774         mNbSocketCreated = 0;
   1775         mIsNfcEnabled = false;
   1776         mSelectedSeId = 0;
   1777     }
   1778 
   1779     private synchronized Object findObject(int key) {
   1780         Object device = null;
   1781 
   1782         device = mObjectMap.get(key);
   1783         if (device == null) {
   1784             Log.w(TAG, "Handle not found !");
   1785         }
   1786 
   1787         return device;
   1788     }
   1789 
   1790     synchronized void registerTagObject(NativeNfcTag nativeTag) {
   1791         mObjectMap.put(nativeTag.getHandle(), nativeTag);
   1792     }
   1793 
   1794     synchronized void unregisterObject(int handle) {
   1795         mObjectMap.remove(handle);
   1796     }
   1797 
   1798     private synchronized Object findSocket(int key) {
   1799         Object socket = null;
   1800 
   1801         socket = mSocketMap.get(key);
   1802 
   1803         return socket;
   1804     }
   1805 
   1806     private void RemoveSocket(int key) {
   1807         mSocketMap.remove(key);
   1808     }
   1809 
   1810     private boolean CheckSocketSap(int sap) {
   1811         /* List of sockets registered */
   1812         ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
   1813 
   1814         while (it.hasNext()) {
   1815             RegisteredSocket registeredSocket = it.next();
   1816 
   1817             if (sap == registeredSocket.mSap) {
   1818                 /* SAP already used */
   1819                 return false;
   1820             }
   1821         }
   1822         return true;
   1823     }
   1824 
   1825     private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
   1826 
   1827         if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) {
   1828             return false;
   1829         }
   1830         return true;
   1831     }
   1832 
   1833     private boolean CheckSocketServiceName(String sn) {
   1834 
   1835         /* List of sockets registered */
   1836         ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
   1837 
   1838         while (it.hasNext()) {
   1839             RegisteredSocket registeredSocket = it.next();
   1840 
   1841             if (sn.equals(registeredSocket.mServiceName)) {
   1842                 /* Service Name already used */
   1843                 return false;
   1844             }
   1845         }
   1846         return true;
   1847     }
   1848 
   1849     private void RemoveRegisteredSocket(int nativeHandle) {
   1850         /* check if sockets are registered */
   1851         ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
   1852 
   1853         while (it.hasNext()) {
   1854             RegisteredSocket registeredSocket = it.next();
   1855             if (registeredSocket.mHandle == nativeHandle) {
   1856                 /* remove the registered socket from the list */
   1857                 it.remove();
   1858                 if (DBG) Log.d(TAG, "socket removed");
   1859             }
   1860         }
   1861     }
   1862 
   1863     /*
   1864      * RegisteredSocket class to store the creation request of socket until the
   1865      * LLCP link in not activated
   1866      */
   1867     private class RegisteredSocket {
   1868         private final int mType;
   1869 
   1870         private final int mHandle;
   1871 
   1872         private final int mSap;
   1873 
   1874         private int mMiu;
   1875 
   1876         private int mRw;
   1877 
   1878         private String mServiceName;
   1879 
   1880         private int mlinearBufferLength;
   1881 
   1882         RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
   1883                 int linearBufferLength) {
   1884             mType = type;
   1885             mHandle = handle;
   1886             mSap = sap;
   1887             mServiceName = sn;
   1888             mRw = rw;
   1889             mMiu = miu;
   1890             mlinearBufferLength = linearBufferLength;
   1891         }
   1892 
   1893         RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
   1894             mType = type;
   1895             mHandle = handle;
   1896             mSap = sap;
   1897             mRw = rw;
   1898             mMiu = miu;
   1899             mlinearBufferLength = linearBufferLength;
   1900         }
   1901 
   1902         RegisteredSocket(int type, int handle, int sap) {
   1903             mType = type;
   1904             mHandle = handle;
   1905             mSap = sap;
   1906         }
   1907     }
   1908 
   1909     /** For use by code in this process */
   1910     public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
   1911         try {
   1912             int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
   1913             if (ErrorCodes.isError(handle)) {
   1914                 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
   1915                 return null;
   1916             }
   1917             return new LlcpSocket(mLlcpSocket, handle);
   1918         } catch (RemoteException e) {
   1919             // This will never happen since the code is calling into it's own process
   1920             throw new IllegalStateException("unable to talk to myself", e);
   1921         }
   1922     }
   1923 
   1924     /** For use by code in this process */
   1925     public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
   1926             int linearBufferLength) {
   1927         try {
   1928             int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
   1929             if (ErrorCodes.isError(handle)) {
   1930                 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
   1931                 return null;
   1932             }
   1933             return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
   1934         } catch (RemoteException e) {
   1935             // This will never happen since the code is calling into it's own process
   1936             throw new IllegalStateException("unable to talk to myself", e);
   1937         }
   1938     }
   1939 
   1940     private void activateLlcpLink() {
   1941         /* check if sockets are registered */
   1942         ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
   1943 
   1944         if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
   1945 
   1946         /* Mark the link state */
   1947         mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED;
   1948 
   1949         while (it.hasNext()) {
   1950             RegisteredSocket registeredSocket = it.next();
   1951 
   1952             switch (registeredSocket.mType) {
   1953             case LLCP_SERVICE_SOCKET_TYPE:
   1954                 if (DBG) Log.d(TAG, "Registered Llcp Service Socket");
   1955                 if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName);
   1956                 NativeLlcpServiceSocket serviceSocket;
   1957 
   1958                 serviceSocket = mManager.doCreateLlcpServiceSocket(
   1959                         registeredSocket.mSap, registeredSocket.mServiceName,
   1960                         registeredSocket.mMiu, registeredSocket.mRw,
   1961                         registeredSocket.mlinearBufferLength);
   1962 
   1963                 if (serviceSocket != null) {
   1964                     if (DBG) Log.d(TAG, "service socket created");
   1965                     /* Add the socket into the socket map */
   1966                     synchronized(NfcService.this) {
   1967                         mSocketMap.put(registeredSocket.mHandle, serviceSocket);
   1968                     }
   1969                 } else {
   1970                     Log.d(TAG, "FAILED to create service socket");
   1971                     /* socket creation error - update the socket
   1972                      * handle counter */
   1973                     mGeneratedSocketHandle -= 1;
   1974                 }
   1975 
   1976                 // NOTE: don't remove this socket from the registered sockets list.
   1977                 // If it's removed it won't be created the next time an LLCP
   1978                 // connection is activated and the server won't be found.
   1979                 break;
   1980 
   1981             case LLCP_SOCKET_TYPE:
   1982                 if (DBG) Log.d(TAG, "Registered Llcp Socket");
   1983                 NativeLlcpSocket clientSocket;
   1984                 clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
   1985                         registeredSocket.mMiu, registeredSocket.mRw,
   1986                         registeredSocket.mlinearBufferLength);
   1987                 if (clientSocket != null) {
   1988                     if (DBG) Log.d(TAG, "socket created");
   1989                     /* Add the socket into the socket map */
   1990                     synchronized(NfcService.this) {
   1991                         mSocketMap.put(registeredSocket.mHandle, clientSocket);
   1992                     }
   1993                 } else {
   1994                     Log.d(TAG, "FAILED to create service socket");
   1995                     /* socket creation error - update the socket
   1996                      * handle counter */
   1997                     mGeneratedSocketHandle -= 1;
   1998                 }
   1999                 // This socket has been created, remove it from the registered sockets list.
   2000                 it.remove();
   2001                 break;
   2002 
   2003             case LLCP_CONNECTIONLESS_SOCKET_TYPE:
   2004                 if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket");
   2005                 NativeLlcpConnectionlessSocket connectionlessSocket;
   2006                 connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket(
   2007                         registeredSocket.mSap);
   2008                 if (connectionlessSocket != null) {
   2009                     if (DBG) Log.d(TAG, "connectionless socket created");
   2010                     /* Add the socket into the socket map */
   2011                     synchronized(NfcService.this) {
   2012                         mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
   2013                     }
   2014                 } else {
   2015                     Log.d(TAG, "FAILED to create service socket");
   2016                     /* socket creation error - update the socket
   2017                      * handle counter */
   2018                     mGeneratedSocketHandle -= 1;
   2019                 }
   2020                 // This socket has been created, remove it from the registered sockets list.
   2021                 it.remove();
   2022                 break;
   2023             }
   2024         }
   2025 
   2026         /* Broadcast Intent Link LLCP activated */
   2027         Intent LlcpLinkIntent = new Intent();
   2028         LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
   2029 
   2030         LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
   2031                 NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
   2032 
   2033         if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
   2034         mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
   2035     }
   2036 
   2037     void sendMessage(int what, Object obj) {
   2038         Message msg = mHandler.obtainMessage();
   2039         msg.what = what;
   2040         msg.obj = obj;
   2041         mHandler.sendMessage(msg);
   2042     }
   2043 
   2044     private final Handler mHandler = new Handler() {
   2045         @Override
   2046         public void handleMessage(Message msg) {
   2047            switch (msg.what) {
   2048            case MSG_NDEF_TAG:
   2049                if (DBG) Log.d(TAG, "Tag detected, notifying applications");
   2050                NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
   2051                if (nativeTag.connect()) {
   2052                    if (nativeTag.checkNdef()) {
   2053                        boolean generateEmptyIntent = false;
   2054                        byte[] buff = nativeTag.read();
   2055                        if (buff != null) {
   2056                            NdefMessage[] msgNdef = new NdefMessage[1];
   2057                            try {
   2058                                msgNdef[0] = new NdefMessage(buff);
   2059                                NdefTag tag = new NdefTag(nativeTag.getUid(),
   2060                                        TagTarget.internalTypeToRawTargets(nativeTag.getType()),
   2061                                        nativeTag.getPollBytes(), nativeTag.getActivationBytes(),
   2062                                        nativeTag.getHandle(),
   2063                                        TagTarget.internalTypeToNdefTargets(nativeTag.getType()),
   2064                                        new NdefMessage[][] {msgNdef});
   2065                                Intent intent = buildNdefTagIntent(tag);
   2066                                if (DBG) Log.d(TAG, "NDEF tag found, starting corresponding activity");
   2067                                if (DBG) Log.d(TAG, tag.toString());
   2068                                try {
   2069                                    mContext.startActivity(intent);
   2070                                    registerTagObject(nativeTag);
   2071                                } catch (ActivityNotFoundException e) {
   2072                                    Log.w(TAG, "No activity found, disconnecting");
   2073                                    nativeTag.disconnect();
   2074                                }
   2075                            } catch (FormatException e) {
   2076                                // Create an intent anyway, without NDEF messages
   2077                                generateEmptyIntent = true;
   2078                            }
   2079                        } else {
   2080                            // Create an intent anyway, without NDEF messages
   2081                            generateEmptyIntent = true;
   2082                        }
   2083                        if (generateEmptyIntent) {
   2084                            // Create an intent with an empty ndef message array
   2085                            NdefTag tag = new NdefTag(nativeTag.getUid(),
   2086                                    TagTarget.internalTypeToRawTargets(nativeTag.getType()),
   2087                                    nativeTag.getPollBytes(), nativeTag.getActivationBytes(),
   2088                                    nativeTag.getHandle(),
   2089                                    TagTarget.internalTypeToNdefTargets(nativeTag.getType()),
   2090                                    new NdefMessage[][] { {} });
   2091                            Intent intent = buildNdefTagIntent(tag);
   2092                            if (DBG) Log.d(TAG, "NDEF tag found, but length 0 or invalid format, starting corresponding activity");
   2093                            try {
   2094                                mContext.startActivity(intent);
   2095                                registerTagObject(nativeTag);
   2096                            } catch (ActivityNotFoundException e) {
   2097                                Log.w(TAG, "No activity found, disconnecting");
   2098                                nativeTag.disconnect();
   2099                            }
   2100                        }
   2101                    } else {
   2102                        Intent intent = new Intent();
   2103                        Tag tag = new Tag(nativeTag.getUid(), false,
   2104                                TagTarget.internalTypeToRawTargets(nativeTag.getType()),
   2105                                nativeTag.getPollBytes(), nativeTag.getActivationBytes(),
   2106                                nativeTag.getHandle());
   2107                        intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED);
   2108                        intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
   2109                        intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
   2110                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2111                        if (DBG) Log.d(TAG, "Non-NDEF tag found, starting corresponding activity");
   2112                        if (DBG) Log.d(TAG, tag.toString());
   2113                        try {
   2114                            mContext.startActivity(intent);
   2115                            registerTagObject(nativeTag);
   2116                        } catch (ActivityNotFoundException e) {
   2117                            Log.w(TAG, "No activity found, disconnecting");
   2118                            nativeTag.disconnect();
   2119                        }
   2120                    }
   2121                } else {
   2122                    Log.w(TAG, "Failed to connect to tag");
   2123                    nativeTag.disconnect();
   2124                }
   2125                break;
   2126            case MSG_CARD_EMULATION:
   2127                if (DBG) Log.d(TAG, "Card Emulation message");
   2128                byte[] aid = (byte[]) msg.obj;
   2129                /* Send broadcast ordered */
   2130                Intent TransactionIntent = new Intent();
   2131                TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
   2132                TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
   2133                if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
   2134                mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
   2135                break;
   2136 
   2137            case MSG_LLCP_LINK_ACTIVATION:
   2138                NativeP2pDevice device = (NativeP2pDevice) msg.obj;
   2139 
   2140                Log.d(TAG, "LLCP Activation message");
   2141 
   2142                if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
   2143                    if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
   2144                    if (device.doConnect()) {
   2145                        /* Check Llcp compliancy */
   2146                        if (mManager.doCheckLlcp()) {
   2147                            /* Activate Llcp Link */
   2148                            if (mManager.doActivateLlcp()) {
   2149                                if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
   2150                                activateLlcpLink();
   2151                            } else {
   2152                                /* should not happen */
   2153                                Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
   2154                                device.doDisconnect();
   2155                            }
   2156 
   2157                        } else {
   2158                            if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
   2159                            device.doDisconnect();
   2160                        }
   2161                    } else {
   2162                        if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop.");
   2163                        /* resume should be done in doConnect */
   2164                    }
   2165 
   2166                } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
   2167                    if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
   2168                    /* Check Llcp compliancy */
   2169                    if (mManager.doCheckLlcp()) {
   2170                        /* Activate Llcp Link */
   2171                        if (mManager.doActivateLlcp()) {
   2172                            if (DBG) Log.d(TAG, "Target Activate LLCP OK");
   2173                            activateLlcpLink();
   2174                       }
   2175                    } else {
   2176                        Log.w(TAG, "checkLlcp failed");
   2177                    }
   2178                }
   2179                break;
   2180 
   2181            case MSG_LLCP_LINK_DEACTIVATED:
   2182                device = (NativeP2pDevice) msg.obj;
   2183 
   2184                Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
   2185                if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
   2186                    if (DBG) Log.d(TAG, "disconnecting from target");
   2187                    /* Restart polling loop */
   2188                    device.doDisconnect();
   2189                } else {
   2190                    if (DBG) Log.d(TAG, "not disconnecting from initiator");
   2191                }
   2192 
   2193                /* Mark the link state */
   2194                mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
   2195 
   2196                /* Broadcast Intent Link LLCP activated */
   2197                Intent LlcpLinkIntent = new Intent();
   2198                LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
   2199                LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
   2200                        NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
   2201                if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
   2202                mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
   2203                break;
   2204 
   2205            case MSG_TARGET_DESELECTED:
   2206                /* Broadcast Intent Target Deselected */
   2207                if (DBG) Log.d(TAG, "Target Deselected");
   2208                Intent TargetDeselectedIntent = new Intent();
   2209                TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
   2210                if (DBG) Log.d(TAG, "Broadcasting Intent");
   2211                mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
   2212                break;
   2213 
   2214            default:
   2215                Log.e(TAG, "Unknown message received");
   2216                break;
   2217            }
   2218         }
   2219 
   2220         private Intent buildNdefTagIntent(NdefTag tag) {
   2221             Intent intent = new Intent();
   2222                intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED);
   2223                intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
   2224                intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
   2225                intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, tag.getNdefMessages());
   2226                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2227             return intent;
   2228         }
   2229     };
   2230 
   2231     private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
   2232         @Override
   2233         protected Void doInBackground(Boolean... enable) {
   2234             if (enable != null && enable.length > 0 && enable[0]) {
   2235                 synchronized (NfcService.this) {
   2236                     mScreenOn = true;
   2237                     maybeEnableDiscovery();
   2238                 }
   2239             } else {
   2240                 mWakeLock.acquire();
   2241                 synchronized (NfcService.this) {
   2242                     mScreenOn = false;
   2243                     maybeDisableDiscovery();
   2244                 }
   2245                 mWakeLock.release();
   2246             }
   2247             return null;
   2248         }
   2249     }
   2250 
   2251     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
   2252         @Override
   2253         public void onReceive(Context context, Intent intent) {
   2254             if (intent.getAction().equals(
   2255                     NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
   2256                 if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
   2257 
   2258                 /* Restart polling loop for notification */
   2259                 maybeEnableDiscovery();
   2260 
   2261             } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
   2262                 // Perform discovery enable in thread to protect against ANR when the
   2263                 // NFC stack wedges. This is *not* the correct way to fix this issue -
   2264                 // configuration of the local NFC adapter should be very quick and should
   2265                 // be safe on the main thread, and the NFC stack should not wedge.
   2266                 new EnableDisableDiscoveryTask().execute(new Boolean(true));
   2267             } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
   2268                 // Perform discovery disable in thread to protect against ANR when the
   2269                 // NFC stack wedges. This is *not* the correct way to fix this issue -
   2270                 // configuration of the local NFC adapter should be very quick and should
   2271                 // be safe on the main thread, and the NFC stack should not wedge.
   2272                 new EnableDisableDiscoveryTask().execute(new Boolean(false));
   2273             }
   2274         }
   2275     };
   2276 }
   2277