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