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