NfcService.java revision ef92efa7fd86d75cc35465b84e8740f941ff0f0a
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
17package com.android.nfc;
18
19import com.android.internal.nfc.LlcpServiceSocket;
20import com.android.internal.nfc.LlcpSocket;
21
22import android.app.Application;
23import android.content.ActivityNotFoundException;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.SharedPreferences;
29import android.nfc.ErrorCodes;
30import android.nfc.FormatException;
31import android.nfc.ILlcpConnectionlessSocket;
32import android.nfc.ILlcpServiceSocket;
33import android.nfc.ILlcpSocket;
34import android.nfc.INfcAdapter;
35import android.nfc.INfcTag;
36import android.nfc.IP2pInitiator;
37import android.nfc.IP2pTarget;
38import android.nfc.LlcpPacket;
39import android.nfc.NdefMessage;
40import android.nfc.NdefTag;
41import android.nfc.NfcAdapter;
42import android.nfc.Tag;
43import android.os.AsyncTask;
44import android.os.Handler;
45import android.os.Message;
46import android.os.PowerManager;
47import android.os.RemoteException;
48import android.os.ServiceManager;
49import android.util.Log;
50
51import java.util.HashMap;
52import java.util.LinkedList;
53import java.util.ListIterator;
54
55public 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