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