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