NfcService.java revision 05973d55daf68a286c932ee4e7ffbd6bb53789e0
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.Activity;
25import android.app.Application;
26import android.app.PendingIntent;
27import android.app.PendingIntent.CanceledException;
28import android.app.StatusBarManager;
29import android.content.ActivityNotFoundException;
30import android.content.BroadcastReceiver;
31import android.content.ComponentName;
32import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
35import android.content.SharedPreferences;
36import android.net.Uri;
37import android.nfc.ErrorCodes;
38import android.nfc.FormatException;
39import android.nfc.ILlcpConnectionlessSocket;
40import android.nfc.ILlcpServiceSocket;
41import android.nfc.ILlcpSocket;
42import android.nfc.INfcAdapter;
43import android.nfc.INfcSecureElement;
44import android.nfc.INfcTag;
45import android.nfc.IP2pInitiator;
46import android.nfc.IP2pTarget;
47import android.nfc.LlcpPacket;
48import android.nfc.NdefMessage;
49import android.nfc.NdefRecord;
50import android.nfc.NfcAdapter;
51import android.nfc.Tag;
52import android.os.AsyncTask;
53import android.os.Bundle;
54import android.os.Handler;
55import android.os.Message;
56import android.os.PowerManager;
57import android.os.RemoteException;
58import android.os.ServiceManager;
59import android.util.Log;
60
61import java.io.ByteArrayOutputStream;
62import java.io.FileInputStream;
63import java.io.FileNotFoundException;
64import java.io.FileOutputStream;
65import java.io.IOException;
66import java.nio.charset.Charsets;
67import java.util.Arrays;
68import java.util.HashMap;
69import java.util.LinkedList;
70import java.util.ListIterator;
71import java.util.Timer;
72import java.util.TimerTask;
73
74public class NfcService extends Application {
75    static final boolean DBG = false;
76
77    private static final String MY_TAG_FILE_NAME = "mytag";
78
79    static {
80        System.loadLibrary("nfc_jni");
81    }
82
83    /**
84     * NFC Forum "URI Record Type Definition"
85     *
86     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
87     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
88     */
89    private static final String[] URI_PREFIX_MAP = new String[] {
90            "", // 0x00
91            "http://www.", // 0x01
92            "https://www.", // 0x02
93            "http://", // 0x03
94            "https://", // 0x04
95            "tel:", // 0x05
96            "mailto:", // 0x06
97            "ftp://anonymous:anonymous@", // 0x07
98            "ftp://ftp.", // 0x08
99            "ftps://", // 0x09
100            "sftp://", // 0x0A
101            "smb://", // 0x0B
102            "nfs://", // 0x0C
103            "ftp://", // 0x0D
104            "dav://", // 0x0E
105            "news:", // 0x0F
106            "telnet://", // 0x10
107            "imap:", // 0x11
108            "rtsp://", // 0x12
109            "urn:", // 0x13
110            "pop:", // 0x14
111            "sip:", // 0x15
112            "sips:", // 0x16
113            "tftp:", // 0x17
114            "btspp://", // 0x18
115            "btl2cap://", // 0x19
116            "btgoep://", // 0x1A
117            "tcpobex://", // 0x1B
118            "irdaobex://", // 0x1C
119            "file://", // 0x1D
120            "urn:epc:id:", // 0x1E
121            "urn:epc:tag:", // 0x1F
122            "urn:epc:pat:", // 0x20
123            "urn:epc:raw:", // 0x21
124            "urn:epc:", // 0x22
125    };
126
127    public static final String SERVICE_NAME = "nfc";
128
129    private static final String TAG = "NfcService";
130
131    private static final String NFC_PERM = android.Manifest.permission.NFC;
132    private static final String NFC_PERM_ERROR = "NFC permission required";
133    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
134    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
135
136    private static final String PREF = "NfcServicePrefs";
137
138    private static final String PREF_NFC_ON = "nfc_on";
139    private static final boolean NFC_ON_DEFAULT = true;
140
141    private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
142    private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
143
144    private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
145    private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
146
147    private static final String PREF_LLCP_LTO = "llcp_lto";
148    private static final int LLCP_LTO_DEFAULT = 150;
149    private static final int LLCP_LTO_MAX = 255;
150
151    /** Maximum Information Unit */
152    private static final String PREF_LLCP_MIU = "llcp_miu";
153    private static final int LLCP_MIU_DEFAULT = 128;
154    private static final int LLCP_MIU_MAX = 2176;
155
156    /** Well Known Service List */
157    private static final String PREF_LLCP_WKS = "llcp_wks";
158    private static final int LLCP_WKS_DEFAULT = 1;
159    private static final int LLCP_WKS_MAX = 15;
160
161    private static final String PREF_LLCP_OPT = "llcp_opt";
162    private static final int LLCP_OPT_DEFAULT = 0;
163    private static final int LLCP_OPT_MAX = 3;
164
165    private static final String PREF_DISCOVERY_A = "discovery_a";
166    private static final boolean DISCOVERY_A_DEFAULT = true;
167
168    private static final String PREF_DISCOVERY_B = "discovery_b";
169    private static final boolean DISCOVERY_B_DEFAULT = true;
170
171    private static final String PREF_DISCOVERY_F = "discovery_f";
172    private static final boolean DISCOVERY_F_DEFAULT = true;
173
174    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
175    private static final boolean DISCOVERY_15693_DEFAULT = true;
176
177    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
178    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
179
180    /** NFC Reader Discovery mode for enableDiscovery() */
181    private static final int DISCOVERY_MODE_READER = 0;
182
183    /** Card Emulation Discovery mode for enableDiscovery() */
184    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
185
186    private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
187    private static final int LLCP_SOCKET_TYPE = 1;
188    private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
189    private static final int LLCP_SOCKET_NB_MAX = 5;  // Maximum number of socket managed
190    private static final int LLCP_RW_MAX_VALUE = 15;  // Receive Window
191
192    private static final int PROPERTY_LLCP_LTO = 0;
193    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
194    private static final int PROPERTY_LLCP_MIU = 1;
195    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
196    private static final int PROPERTY_LLCP_WKS = 2;
197    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
198    private static final int PROPERTY_LLCP_OPT = 3;
199    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
200    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
201    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
202    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
203    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
204    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
205    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
206    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
207    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
208    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
209    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
210
211    static final int MSG_NDEF_TAG = 0;
212    static final int MSG_CARD_EMULATION = 1;
213    static final int MSG_LLCP_LINK_ACTIVATION = 2;
214    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
215    static final int MSG_TARGET_DESELECTED = 4;
216    static final int MSG_SHOW_MY_TAG_ICON = 5;
217    static final int MSG_HIDE_MY_TAG_ICON = 6;
218    static final int MSG_MOCK_NDEF = 7;
219    static final int MSG_SE_FIELD_ACTIVATED = 8;
220    static final int MSG_SE_FIELD_DEACTIVATED = 9;
221
222    // Locked on mNfcAdapter
223    IntentFilter[] mDispatchOverrideFilters;
224    PendingIntent mDispatchOverrideIntent;
225
226    // TODO: none of these appear to be synchronized but are
227    // read/written from different threads (notably Binder threads)...
228    private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
229    private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
230    private int mGeneratedSocketHandle = 0;
231    private int mNbSocketCreated = 0;
232    private volatile boolean mIsNfcEnabled = false;
233    private int mSelectedSeId = 0;
234    private boolean mNfcSecureElementState;
235
236    // Secure element
237    private Timer mTimerOpenSmx;
238    private boolean isClosed = false;
239    private boolean isOpened = false;
240    private boolean mOpenSmxPending = false;
241    private NativeNfcSecureElement mSecureElement;
242    private int mSecureElementHandle;
243
244    // fields below are used in multiple threads and protected by synchronized(this)
245    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
246    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
247    private boolean mScreenOn;
248
249    // fields below are final after onCreate()
250    Context mContext;
251    private NativeNfcManager mManager;
252    private SharedPreferences mPrefs;
253    private SharedPreferences.Editor mPrefsEditor;
254    private PowerManager.WakeLock mWakeLock;
255    private MyTagServer mMyTagServer;
256    private MyTagClient mMyTagClient;
257
258    private static NfcService sService;
259
260    public static NfcService getInstance() {
261        return sService;
262    }
263
264    @Override
265    public void onCreate() {
266        super.onCreate();
267
268        Log.i(TAG, "Starting NFC service");
269
270        sService = this;
271
272        mContext = this;
273        mManager = new NativeNfcManager(mContext, this);
274        mManager.initializeNativeStructure();
275
276        mMyTagServer = new MyTagServer();
277        mMyTagClient = new MyTagClient(this);
278
279        mSecureElement = new NativeNfcSecureElement();
280
281        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
282        mPrefsEditor = mPrefs.edit();
283
284        mIsNfcEnabled = false;  // real preference read later
285
286        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
287        mScreenOn = pm.isScreenOn();
288        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
289
290        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
291
292        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
293        filter.addAction(Intent.ACTION_SCREEN_OFF);
294        filter.addAction(Intent.ACTION_SCREEN_ON);
295        mContext.registerReceiver(mReceiver, filter);
296
297        Thread t = new Thread() {
298            @Override
299            public void run() {
300                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
301                if (nfc_on) {
302                    _enable(false);
303                }
304            }
305        };
306        t.start();
307    }
308
309    @Override
310    public void onTerminate() {
311        super.onTerminate();
312        // NFC application is persistent, it should not be destroyed by framework
313        Log.wtf(TAG, "NFC service is under attack!");
314    }
315
316    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
317        /** Protected by "this" */
318        NdefMessage mLocalMessage = null;
319
320        @Override
321        public boolean enable() throws RemoteException {
322            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
323
324            boolean isSuccess = false;
325            boolean previouslyEnabled = isEnabled();
326            if (!previouslyEnabled) {
327                reset();
328                isSuccess = _enable(previouslyEnabled);
329            }
330            return isSuccess;
331        }
332
333        @Override
334        public boolean disable() throws RemoteException {
335            boolean isSuccess = false;
336            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
337            boolean previouslyEnabled = isEnabled();
338            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
339
340            if (previouslyEnabled) {
341                /* tear down the my tag server */
342                mMyTagServer.stop();
343                isSuccess = mManager.deinitialize();
344                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
345                if (isSuccess) {
346                    mIsNfcEnabled = false;
347                    synchronized (this) {
348                        // Clear out any old dispatch overrides
349                        mDispatchOverrideFilters = null;
350                        mDispatchOverrideIntent = null;
351                    }
352                }
353            }
354
355            updateNfcOnSetting(previouslyEnabled);
356
357            return isSuccess;
358        }
359
360        @Override
361        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
362                IntentFilter[] filters) {
363            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
364            synchronized (this) {
365                if (activity == null || filters == null || filters.length == 0 || intent == null) {
366                    throw new IllegalArgumentException();
367                }
368                if (mDispatchOverrideFilters != null) {
369                    Log.e(TAG, "Replacing active dispatch overrides");
370                }
371                mDispatchOverrideFilters = filters;
372                mDispatchOverrideIntent = intent;
373            }
374        }
375
376        @Override
377        public void disableForegroundDispatch(ComponentName activity) {
378            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
379            synchronized (this) {
380                if (mDispatchOverrideFilters == null && mDispatchOverrideIntent == null) {
381                    Log.e(TAG, "No active foreground dispatching");
382                }
383                mDispatchOverrideFilters = null;
384                mDispatchOverrideIntent = null;
385            }
386        }
387
388        @Override
389        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
390            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
391
392            // Check if NFC is enabled
393            if (!mIsNfcEnabled) {
394                return ErrorCodes.ERROR_NOT_INITIALIZED;
395            }
396
397            /* Check SAP is not already used */
398
399            /* Check nb socket created */
400            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
401                /* Store the socket handle */
402                int sockeHandle = mGeneratedSocketHandle;
403
404                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
405                    NativeLlcpConnectionlessSocket socket;
406
407                    socket = mManager.doCreateLlcpConnectionlessSocket(sap);
408                    if (socket != null) {
409                        synchronized(NfcService.this) {
410                            /* Update the number of socket created */
411                            mNbSocketCreated++;
412
413                            /* Add the socket into the socket map */
414                            mSocketMap.put(sockeHandle, socket);
415                        }
416                        return sockeHandle;
417                    } else {
418                        /*
419                         * socket creation error - update the socket handle
420                         * generation
421                         */
422                        mGeneratedSocketHandle -= 1;
423
424                        /* Get Error Status */
425                        int errorStatus = mManager.doGetLastError();
426
427                        switch (errorStatus) {
428                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
429                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
430                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
431                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
432                            default:
433                                return ErrorCodes.ERROR_SOCKET_CREATION;
434                        }
435                    }
436                } else {
437                    /* Check SAP is not already used */
438                    if (!CheckSocketSap(sap)) {
439                        return ErrorCodes.ERROR_SAP_USED;
440                    }
441
442                    NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
443
444                    synchronized(NfcService.this) {
445                        /* Add the socket into the socket map */
446                        mSocketMap.put(sockeHandle, socket);
447
448                        /* Update the number of socket created */
449                        mNbSocketCreated++;
450                    }
451                    /* Create new registered socket */
452                    RegisteredSocket registeredSocket = new RegisteredSocket(
453                            LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
454
455                    /* Put this socket into a list of registered socket */
456                    mRegisteredSocketList.add(registeredSocket);
457                }
458
459                /* update socket handle generation */
460                mGeneratedSocketHandle++;
461
462                return sockeHandle;
463
464            } else {
465                /* No socket available */
466                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
467            }
468
469        }
470
471        @Override
472        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
473                throws RemoteException {
474            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
475
476            // Check if NFC is enabled
477            if (!mIsNfcEnabled) {
478                return ErrorCodes.ERROR_NOT_INITIALIZED;
479            }
480
481            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
482                int sockeHandle = mGeneratedSocketHandle;
483
484                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
485                    NativeLlcpServiceSocket socket;
486
487                    socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
488                    if (socket != null) {
489                        synchronized(NfcService.this) {
490                            /* Update the number of socket created */
491                            mNbSocketCreated++;
492                            /* Add the socket into the socket map */
493                            mSocketMap.put(sockeHandle, socket);
494                        }
495                    } else {
496                        /* socket creation error - update the socket handle counter */
497                        mGeneratedSocketHandle -= 1;
498
499                        /* Get Error Status */
500                        int errorStatus = mManager.doGetLastError();
501
502                        switch (errorStatus) {
503                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
504                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
505                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
506                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
507                            default:
508                                return ErrorCodes.ERROR_SOCKET_CREATION;
509                        }
510                    }
511                } else {
512
513                    /* Check SAP is not already used */
514                    if (!CheckSocketSap(sap)) {
515                        return ErrorCodes.ERROR_SAP_USED;
516                    }
517
518                    /* Service Name */
519                    if (!CheckSocketServiceName(sn)) {
520                        return ErrorCodes.ERROR_SERVICE_NAME_USED;
521                    }
522
523                    /* Check socket options */
524                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
525                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
526                    }
527
528                    NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw,
529                            linearBufferLength);
530                    synchronized(NfcService.this) {
531                        /* Add the socket into the socket map */
532                        mSocketMap.put(sockeHandle, socket);
533
534                        /* Update the number of socket created */
535                        mNbSocketCreated++;
536                    }
537                    /* Create new registered socket */
538                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
539                            sockeHandle, sap, sn, miu, rw, linearBufferLength);
540
541                    /* Put this socket into a list of registered socket */
542                    mRegisteredSocketList.add(registeredSocket);
543                }
544
545                /* update socket handle generation */
546                mGeneratedSocketHandle += 1;
547
548                if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
549                return sockeHandle;
550            } else {
551                /* No socket available */
552                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
553            }
554        }
555
556        @Override
557        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
558                throws RemoteException {
559            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
560
561            // Check if NFC is enabled
562            if (!mIsNfcEnabled) {
563                return ErrorCodes.ERROR_NOT_INITIALIZED;
564            }
565
566            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
567
568                int sockeHandle = mGeneratedSocketHandle;
569
570                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
571                    if (DBG) Log.d(TAG, "creating llcp socket while activated");
572                    NativeLlcpSocket socket;
573
574                    socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
575
576                    if (socket != null) {
577                        synchronized(NfcService.this) {
578                            /* Update the number of socket created */
579                            mNbSocketCreated++;
580                            /* Add the socket into the socket map */
581                            mSocketMap.put(sockeHandle, socket);
582                        }
583                    } else {
584                        /*
585                         * socket creation error - update the socket handle
586                         * generation
587                         */
588                        mGeneratedSocketHandle -= 1;
589
590                        /* Get Error Status */
591                        int errorStatus = mManager.doGetLastError();
592
593                        Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
594
595                        switch (errorStatus) {
596                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
597                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
598                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
599                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
600                            default:
601                                return ErrorCodes.ERROR_SOCKET_CREATION;
602                        }
603                    }
604                } else {
605                    if (DBG) Log.d(TAG, "registering llcp socket while not activated");
606
607                    /* Check SAP is not already used */
608                    if (!CheckSocketSap(sap)) {
609                        return ErrorCodes.ERROR_SAP_USED;
610                    }
611
612                    /* Check Socket options */
613                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
614                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
615                    }
616
617                    NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
618                    synchronized(NfcService.this) {
619                        /* Add the socket into the socket map */
620                        mSocketMap.put(sockeHandle, socket);
621
622                        /* Update the number of socket created */
623                        mNbSocketCreated++;
624                    }
625                    /* Create new registered socket */
626                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
627                            sockeHandle, sap, miu, rw, linearBufferLength);
628
629                    /* Put this socket into a list of registered socket */
630                    mRegisteredSocketList.add(registeredSocket);
631                }
632
633                /* update socket handle generation */
634                mGeneratedSocketHandle++;
635
636                return sockeHandle;
637            } else {
638                /* No socket available */
639                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
640            }
641        }
642
643        @Override
644        public int deselectSecureElement() throws RemoteException {
645            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
646
647            // Check if NFC is enabled
648            if (!mIsNfcEnabled) {
649                return ErrorCodes.ERROR_NOT_INITIALIZED;
650            }
651
652            if (mSelectedSeId == 0) {
653                return ErrorCodes.ERROR_NO_SE_CONNECTED;
654            }
655
656            mManager.doDeselectSecureElement(mSelectedSeId);
657            mNfcSecureElementState = false;
658            mSelectedSeId = 0;
659
660            /* store preference */
661            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
662            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
663            mPrefsEditor.apply();
664
665            return ErrorCodes.SUCCESS;
666        }
667
668        @Override
669        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
670            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
671            return mLlcpConnectionlessSocketService;
672        }
673
674        @Override
675        public ILlcpSocket getLlcpInterface() throws RemoteException {
676            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
677            return mLlcpSocket;
678        }
679
680        @Override
681        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
682            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
683            return mLlcpServerSocketService;
684        }
685
686        @Override
687        public INfcTag getNfcTagInterface() throws RemoteException {
688            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
689            return mNfcTagService;
690        }
691
692        @Override
693        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
694            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
695            return mP2pInitiatorService;
696        }
697
698        @Override
699        public IP2pTarget getP2pTargetInterface() throws RemoteException {
700            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
701            return mP2pTargetService;
702        }
703
704        public INfcSecureElement getNfcSecureElementInterface() {
705            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
706            return mSecureElementService;
707        }
708
709        @Override
710        public String getProperties(String param) throws RemoteException {
711            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
712
713            if (param == null) {
714                return null;
715            }
716
717            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
718                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
719            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
720                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
721            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
722                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
723            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
724                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
725            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
726                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
727            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
728                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
729            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
730                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
731            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
732                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
733            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
734                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
735            } else {
736                return "Unknown property";
737            }
738        }
739
740        @Override
741        public int[] getSecureElementList() throws RemoteException {
742            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
743
744            int[] list = null;
745            if (mIsNfcEnabled == true) {
746                list = mManager.doGetSecureElementList();
747            }
748            return list;
749        }
750
751        @Override
752        public int getSelectedSecureElement() throws RemoteException {
753            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
754
755            return mSelectedSeId;
756        }
757
758        @Override
759        public boolean isEnabled() throws RemoteException {
760            return mIsNfcEnabled;
761        }
762
763        @Override
764        public void openTagConnection(Tag tag) throws RemoteException {
765            // TODO: Remove obsolete code
766        }
767
768        @Override
769        public int selectSecureElement(int seId) throws RemoteException {
770            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
771
772            // Check if NFC is enabled
773            if (!mIsNfcEnabled) {
774                return ErrorCodes.ERROR_NOT_INITIALIZED;
775            }
776
777            if (mSelectedSeId == seId) {
778                return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
779            }
780
781            if (mSelectedSeId != 0) {
782                return ErrorCodes.ERROR_SE_CONNECTED;
783            }
784
785            mSelectedSeId = seId;
786            mManager.doSelectSecureElement(mSelectedSeId);
787
788            /* store */
789            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
790            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
791            mPrefsEditor.apply();
792
793            mNfcSecureElementState = true;
794
795            return ErrorCodes.SUCCESS;
796
797        }
798
799        @Override
800        public int setProperties(String param, String value) throws RemoteException {
801            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
802
803            if (isEnabled()) {
804                return ErrorCodes.ERROR_NFC_ON;
805            }
806
807            int val;
808
809            /* Check params validity */
810            if (param == null || value == null) {
811                return ErrorCodes.ERROR_INVALID_PARAM;
812            }
813
814            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
815                val = Integer.parseInt(value);
816
817                /* Check params */
818                if (val > LLCP_LTO_MAX)
819                    return ErrorCodes.ERROR_INVALID_PARAM;
820
821                /* Store value */
822                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
823                mPrefsEditor.apply();
824
825                /* Update JNI */
826                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
827
828            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
829                val = Integer.parseInt(value);
830
831                /* Check params */
832                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
833                    return ErrorCodes.ERROR_INVALID_PARAM;
834
835                /* Store value */
836                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
837                mPrefsEditor.apply();
838
839                /* Update JNI */
840                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
841
842            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
843                val = Integer.parseInt(value);
844
845                /* Check params */
846                if (val > LLCP_WKS_MAX)
847                    return ErrorCodes.ERROR_INVALID_PARAM;
848
849                /* Store value */
850                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
851                mPrefsEditor.apply();
852
853                /* Update JNI */
854                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
855
856            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
857                val = Integer.parseInt(value);
858
859                /* Check params */
860                if (val > LLCP_OPT_MAX)
861                    return ErrorCodes.ERROR_INVALID_PARAM;
862
863                /* Store value */
864                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
865                mPrefsEditor.apply();
866
867                /* Update JNI */
868                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
869
870            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
871                boolean b = Boolean.parseBoolean(value);
872
873                /* Store value */
874                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
875                mPrefsEditor.apply();
876
877                /* Update JNI */
878                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
879
880            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
881                boolean b = Boolean.parseBoolean(value);
882
883                /* Store value */
884                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
885                mPrefsEditor.apply();
886
887                /* Update JNI */
888                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
889
890            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
891                boolean b = Boolean.parseBoolean(value);
892
893                /* Store value */
894                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
895                mPrefsEditor.apply();
896
897                /* Update JNI */
898                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
899
900            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
901                boolean b = Boolean.parseBoolean(value);
902
903                /* Store value */
904                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
905                mPrefsEditor.apply();
906
907                /* Update JNI */
908                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
909
910            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
911                boolean b = Boolean.parseBoolean(value);
912
913                /* Store value */
914                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
915                mPrefsEditor.apply();
916
917                /* Update JNI */
918                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
919
920            } else {
921                return ErrorCodes.ERROR_INVALID_PARAM;
922            }
923
924            return ErrorCodes.SUCCESS;
925        }
926
927        @Override
928        public NdefMessage localGet() throws RemoteException {
929            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
930
931            synchronized (this) {
932                return mLocalMessage;
933            }
934        }
935
936        @Override
937        public void localSet(NdefMessage message) throws RemoteException {
938            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
939
940            synchronized (this) {
941                mLocalMessage = message;
942                Context context = NfcService.this.getApplicationContext();
943
944                // Send a message to the UI thread to show or hide the icon so the requests are
945                // serialized and the icon can't get out of sync with reality.
946                if (message != null) {
947                    FileOutputStream out = null;
948
949                    try {
950                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
951                        byte[] bytes = message.toByteArray();
952                        if (bytes.length == 0) {
953                            Log.w(TAG, "Setting a empty mytag");
954                        }
955
956                        out.write(bytes);
957                    } catch (IOException e) {
958                        Log.e(TAG, "Could not write mytag file", e);
959                    } finally {
960                        try {
961                            if (out != null) {
962                                out.flush();
963                                out.close();
964                            }
965                        } catch (IOException e) {
966                            // Ignore
967                        }
968                    }
969
970                    // Only show the icon if NFC is enabled.
971                    if (mIsNfcEnabled) {
972                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
973                    }
974                } else {
975                    context.deleteFile(MY_TAG_FILE_NAME);
976                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
977                }
978            }
979        }
980    };
981
982    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
983
984        private final int CONNECT_FLAG = 0x01;
985        private final int CLOSE_FLAG   = 0x02;
986        private final int RECV_FLAG    = 0x04;
987        private final int SEND_FLAG    = 0x08;
988
989        private int concurrencyFlags;
990        private Object sync;
991
992        @Override
993        public int close(int nativeHandle) throws RemoteException {
994            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
995
996            NativeLlcpSocket socket = null;
997            boolean isSuccess = false;
998
999            // Check if NFC is enabled
1000            if (!mIsNfcEnabled) {
1001                return ErrorCodes.ERROR_NOT_INITIALIZED;
1002            }
1003
1004            /* find the socket in the hmap */
1005            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1006            if (socket != null) {
1007                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1008                    isSuccess = socket.doClose();
1009                    if (isSuccess) {
1010                        /* Remove the socket closed from the hmap */
1011                        RemoveSocket(nativeHandle);
1012                        /* Update mNbSocketCreated */
1013                        mNbSocketCreated--;
1014                        return ErrorCodes.SUCCESS;
1015                    } else {
1016                        return ErrorCodes.ERROR_IO;
1017                    }
1018                } else {
1019                    /* Remove the socket closed from the hmap */
1020                    RemoveSocket(nativeHandle);
1021
1022                    /* Remove registered socket from the list */
1023                    RemoveRegisteredSocket(nativeHandle);
1024
1025                    /* Update mNbSocketCreated */
1026                    mNbSocketCreated--;
1027
1028                    return ErrorCodes.SUCCESS;
1029                }
1030            } else {
1031                return ErrorCodes.ERROR_IO;
1032            }
1033        }
1034
1035        @Override
1036        public int connect(int nativeHandle, int sap) throws RemoteException {
1037            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1038
1039            NativeLlcpSocket socket = null;
1040            boolean isSuccess = false;
1041
1042            // Check if NFC is enabled
1043            if (!mIsNfcEnabled) {
1044                return ErrorCodes.ERROR_NOT_INITIALIZED;
1045            }
1046
1047            /* find the socket in the hmap */
1048            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1049            if (socket != null) {
1050                isSuccess = socket.doConnect(sap);
1051                if (isSuccess) {
1052                    return ErrorCodes.SUCCESS;
1053                } else {
1054                    return ErrorCodes.ERROR_IO;
1055                }
1056            } else {
1057                return ErrorCodes.ERROR_IO;
1058            }
1059
1060        }
1061
1062        @Override
1063        public int connectByName(int nativeHandle, String sn) throws RemoteException {
1064            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1065
1066            NativeLlcpSocket socket = null;
1067            boolean isSuccess = false;
1068
1069            // Check if NFC is enabled
1070            if (!mIsNfcEnabled) {
1071                return ErrorCodes.ERROR_NOT_INITIALIZED;
1072            }
1073
1074            /* find the socket in the hmap */
1075            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1076            if (socket != null) {
1077                isSuccess = socket.doConnectBy(sn);
1078                if (isSuccess) {
1079                    return ErrorCodes.SUCCESS;
1080                } else {
1081                    return ErrorCodes.ERROR_IO;
1082                }
1083            } else {
1084                return ErrorCodes.ERROR_IO;
1085            }
1086
1087        }
1088
1089        @Override
1090        public int getLocalSap(int nativeHandle) throws RemoteException {
1091            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1092
1093            NativeLlcpSocket socket = null;
1094
1095            // Check if NFC is enabled
1096            if (!mIsNfcEnabled) {
1097                return ErrorCodes.ERROR_NOT_INITIALIZED;
1098            }
1099
1100            /* find the socket in the hmap */
1101            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1102            if (socket != null) {
1103                return socket.getSap();
1104            } else {
1105                return 0;
1106            }
1107        }
1108
1109        @Override
1110        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1111            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1112
1113            NativeLlcpSocket socket = null;
1114
1115            // Check if NFC is enabled
1116            if (!mIsNfcEnabled) {
1117                return ErrorCodes.ERROR_NOT_INITIALIZED;
1118            }
1119
1120            /* find the socket in the hmap */
1121            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1122            if (socket != null) {
1123                return socket.getMiu();
1124            } else {
1125                return 0;
1126            }
1127        }
1128
1129        @Override
1130        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1131            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1132
1133            NativeLlcpSocket socket = null;
1134
1135            // Check if NFC is enabled
1136            if (!mIsNfcEnabled) {
1137                return ErrorCodes.ERROR_NOT_INITIALIZED;
1138            }
1139
1140            /* find the socket in the hmap */
1141            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1142            if (socket != null) {
1143                return socket.getRw();
1144            } else {
1145                return 0;
1146            }
1147        }
1148
1149        @Override
1150        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1151            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1152
1153            NativeLlcpSocket socket = null;
1154
1155            // Check if NFC is enabled
1156            if (!mIsNfcEnabled) {
1157                return ErrorCodes.ERROR_NOT_INITIALIZED;
1158            }
1159
1160            /* find the socket in the hmap */
1161            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1162            if (socket != null) {
1163                if (socket.doGetRemoteSocketMiu() != 0) {
1164                    return socket.doGetRemoteSocketMiu();
1165                } else {
1166                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
1167                }
1168            } else {
1169                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
1170            }
1171        }
1172
1173        @Override
1174        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1175            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1176
1177            NativeLlcpSocket socket = null;
1178
1179            // Check if NFC is enabled
1180            if (!mIsNfcEnabled) {
1181                return ErrorCodes.ERROR_NOT_INITIALIZED;
1182            }
1183
1184            /* find the socket in the hmap */
1185            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1186            if (socket != null) {
1187                if (socket.doGetRemoteSocketRw() != 0) {
1188                    return socket.doGetRemoteSocketRw();
1189                } else {
1190                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
1191                }
1192            } else {
1193                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
1194            }
1195        }
1196
1197        @Override
1198        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1199            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1200
1201            NativeLlcpSocket socket = null;
1202            int receiveLength = 0;
1203
1204            // Check if NFC is enabled
1205            if (!mIsNfcEnabled) {
1206                return ErrorCodes.ERROR_NOT_INITIALIZED;
1207            }
1208
1209            /* find the socket in the hmap */
1210            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1211            if (socket != null) {
1212                return socket.doReceive(receiveBuffer);
1213            } else {
1214                return 0;
1215            }
1216        }
1217
1218        @Override
1219        public int send(int nativeHandle, byte[] data) throws RemoteException {
1220            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1221
1222            NativeLlcpSocket socket = null;
1223            boolean isSuccess = false;
1224
1225            // Check if NFC is enabled
1226            if (!mIsNfcEnabled) {
1227                return ErrorCodes.ERROR_NOT_INITIALIZED;
1228            }
1229
1230            /* find the socket in the hmap */
1231            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1232            if (socket != null) {
1233                isSuccess = socket.doSend(data);
1234                if (isSuccess) {
1235                    return ErrorCodes.SUCCESS;
1236                } else {
1237                    return ErrorCodes.ERROR_IO;
1238                }
1239            } else {
1240                return ErrorCodes.ERROR_IO;
1241            }
1242        }
1243    };
1244
1245    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
1246
1247        @Override
1248        public int accept(int nativeHandle) throws RemoteException {
1249            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1250
1251            NativeLlcpServiceSocket socket = null;
1252            NativeLlcpSocket clientSocket = null;
1253
1254            // Check if NFC is enabled
1255            if (!mIsNfcEnabled) {
1256                return ErrorCodes.ERROR_NOT_INITIALIZED;
1257            }
1258
1259            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
1260                /* find the socket in the hmap */
1261                socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
1262                if (socket != null) {
1263                    clientSocket = socket.doAccept(socket.getMiu(),
1264                            socket.getRw(), socket.getLinearBufferLength());
1265                    if (clientSocket != null) {
1266                        /* Add the socket into the socket map */
1267                        synchronized(this) {
1268                            mSocketMap.put(clientSocket.getHandle(), clientSocket);
1269                            mNbSocketCreated++;
1270                        }
1271                        return clientSocket.getHandle();
1272                    } else {
1273                        return ErrorCodes.ERROR_IO;
1274                    }
1275                } else {
1276                    return ErrorCodes.ERROR_IO;
1277                }
1278            } else {
1279                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
1280            }
1281
1282        }
1283
1284        @Override
1285        public void close(int nativeHandle) throws RemoteException {
1286            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1287
1288            NativeLlcpServiceSocket socket = null;
1289            boolean isSuccess = false;
1290
1291            // Check if NFC is enabled
1292            if (!mIsNfcEnabled) {
1293                return;
1294            }
1295
1296            /* find the socket in the hmap */
1297            boolean closed = false;
1298            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
1299            if (socket != null) {
1300                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1301                    isSuccess = socket.doClose();
1302                    if (isSuccess) {
1303                        closed = true;
1304                    }
1305                } else {
1306                    closed = true;
1307                }
1308            }
1309
1310            // If the socket is closed remove it from the socket lists
1311            if (closed) {
1312                synchronized (this) {
1313                    /* Remove the socket closed from the hmap */
1314                    RemoveSocket(nativeHandle);
1315
1316                    /* Update mNbSocketCreated */
1317                    mNbSocketCreated--;
1318
1319                    /* Remove registered socket from the list */
1320                    RemoveRegisteredSocket(nativeHandle);
1321                }
1322            }
1323        }
1324    };
1325
1326    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1327
1328        @Override
1329        public void close(int nativeHandle) throws RemoteException {
1330            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1331
1332            NativeLlcpConnectionlessSocket socket = null;
1333            boolean isSuccess = false;
1334
1335            // Check if NFC is enabled
1336            if (!mIsNfcEnabled) {
1337                return;
1338            }
1339
1340            /* find the socket in the hmap */
1341            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1342            if (socket != null) {
1343                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1344                    isSuccess = socket.doClose();
1345                    if (isSuccess) {
1346                        /* Remove the socket closed from the hmap */
1347                        RemoveSocket(nativeHandle);
1348                        /* Update mNbSocketCreated */
1349                        mNbSocketCreated--;
1350                    }
1351                } else {
1352                    /* Remove the socket closed from the hmap */
1353                    RemoveSocket(nativeHandle);
1354
1355                    /* Remove registered socket from the list */
1356                    RemoveRegisteredSocket(nativeHandle);
1357
1358                    /* Update mNbSocketCreated */
1359                    mNbSocketCreated--;
1360                }
1361            }
1362        }
1363
1364        @Override
1365        public int getSap(int nativeHandle) throws RemoteException {
1366            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1367
1368            NativeLlcpConnectionlessSocket socket = null;
1369
1370            // Check if NFC is enabled
1371            if (!mIsNfcEnabled) {
1372                return ErrorCodes.ERROR_NOT_INITIALIZED;
1373            }
1374
1375            /* find the socket in the hmap */
1376            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1377            if (socket != null) {
1378                return socket.getSap();
1379            } else {
1380                return 0;
1381            }
1382        }
1383
1384        @Override
1385        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1386            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1387
1388            NativeLlcpConnectionlessSocket socket = null;
1389            LlcpPacket packet;
1390
1391            // Check if NFC is enabled
1392            if (!mIsNfcEnabled) {
1393                return null;
1394            }
1395
1396            /* find the socket in the hmap */
1397            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1398            if (socket != null) {
1399                packet = socket.doReceiveFrom(socket.getLinkMiu());
1400                if (packet != null) {
1401                    return packet;
1402                }
1403                return null;
1404            } else {
1405                return null;
1406            }
1407        }
1408
1409        @Override
1410        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1411            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1412
1413            NativeLlcpConnectionlessSocket socket = null;
1414            boolean isSuccess = false;
1415
1416            // Check if NFC is enabled
1417            if (!mIsNfcEnabled) {
1418                return ErrorCodes.ERROR_NOT_INITIALIZED;
1419            }
1420
1421            /* find the socket in the hmap */
1422            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1423            if (socket != null) {
1424                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1425                if (isSuccess) {
1426                    return ErrorCodes.SUCCESS;
1427                } else {
1428                    return ErrorCodes.ERROR_IO;
1429                }
1430            } else {
1431                return ErrorCodes.ERROR_IO;
1432            }
1433        }
1434    };
1435
1436    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1437
1438        @Override
1439        public int close(int nativeHandle) throws RemoteException {
1440            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1441
1442            NativeNfcTag tag = null;
1443
1444            // Check if NFC is enabled
1445            if (!mIsNfcEnabled) {
1446                return ErrorCodes.ERROR_NOT_INITIALIZED;
1447            }
1448
1449            /* find the tag in the hmap */
1450            tag = (NativeNfcTag) findObject(nativeHandle);
1451            if (tag != null) {
1452                /* Remove the device from the hmap */
1453                unregisterObject(nativeHandle);
1454                tag.disconnect();
1455                return ErrorCodes.SUCCESS;
1456            }
1457            /* Restart polling loop for notification */
1458            maybeEnableDiscovery();
1459            return ErrorCodes.ERROR_DISCONNECT;
1460        }
1461
1462        @Override
1463        public int connect(int nativeHandle, int technology) throws RemoteException {
1464            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1465
1466            NativeNfcTag tag = null;
1467
1468            // Check if NFC is enabled
1469            if (!mIsNfcEnabled) {
1470                return ErrorCodes.ERROR_NOT_INITIALIZED;
1471            }
1472
1473            /* find the tag in the hmap */
1474            tag = (NativeNfcTag) findObject(nativeHandle);
1475            if (tag == null) {
1476                return ErrorCodes.ERROR_DISCONNECT;
1477            }
1478
1479            // Note that on most tags, all technologies are behind a single
1480            // handle. This means that the connect at the lower levels
1481            // will do nothing, as the tag is already connected to that handle.
1482            if (tag.connect(technology)) {
1483                return ErrorCodes.SUCCESS;
1484            } else {
1485                return ErrorCodes.ERROR_DISCONNECT;
1486            }
1487        }
1488
1489        @Override
1490        public int reconnect(int nativeHandle) throws RemoteException {
1491            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1492
1493            NativeNfcTag tag = null;
1494
1495            // Check if NFC is enabled
1496            if (!mIsNfcEnabled) {
1497                return ErrorCodes.ERROR_NOT_INITIALIZED;
1498            }
1499
1500            /* find the tag in the hmap */
1501            tag = (NativeNfcTag) findObject(nativeHandle);
1502            if (tag != null) {
1503                if (tag.reconnect()) {
1504                    return ErrorCodes.SUCCESS;
1505                } else {
1506                    return ErrorCodes.ERROR_DISCONNECT;
1507                }
1508            }
1509            return ErrorCodes.ERROR_DISCONNECT;
1510        }
1511
1512        @Override
1513        public int[] getTechList(int nativeHandle) throws RemoteException {
1514            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1515
1516            // Check if NFC is enabled
1517            if (!mIsNfcEnabled) {
1518                return null;
1519            }
1520
1521            /* find the tag in the hmap */
1522            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1523            if (tag != null) {
1524                return tag.getTechList();
1525            }
1526            return null;
1527        }
1528
1529        @Override
1530        public byte[] getUid(int nativeHandle) throws RemoteException {
1531            NativeNfcTag tag = null;
1532            byte[] uid;
1533
1534            // Check if NFC is enabled
1535            if (!mIsNfcEnabled) {
1536                return null;
1537            }
1538
1539            /* find the tag in the hmap */
1540            tag = (NativeNfcTag) findObject(nativeHandle);
1541            if (tag != null) {
1542                uid = tag.getUid();
1543                return uid;
1544            }
1545            return null;
1546        }
1547
1548        @Override
1549        public boolean isPresent(int nativeHandle) throws RemoteException {
1550            NativeNfcTag tag = null;
1551
1552            // Check if NFC is enabled
1553            if (!mIsNfcEnabled) {
1554                return false;
1555            }
1556
1557            /* find the tag in the hmap */
1558            tag = (NativeNfcTag) findObject(nativeHandle);
1559            if (tag == null) {
1560                return false;
1561            }
1562
1563            return tag.presenceCheck();
1564        }
1565
1566        @Override
1567        public boolean isNdef(int nativeHandle) throws RemoteException {
1568            NativeNfcTag tag = null;
1569            boolean isSuccess = false;
1570
1571            // Check if NFC is enabled
1572            if (!mIsNfcEnabled) {
1573                return isSuccess;
1574            }
1575
1576            /* find the tag in the hmap */
1577            tag = (NativeNfcTag) findObject(nativeHandle);
1578            int[] ndefInfo = new int[2];
1579            if (tag != null) {
1580                isSuccess = tag.checkNdef(ndefInfo);
1581            }
1582            return isSuccess;
1583        }
1584
1585        @Override
1586        public byte[] transceive(int nativeHandle, byte[] data, boolean raw)
1587                throws RemoteException {
1588            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1589
1590            NativeNfcTag tag = null;
1591            byte[] response;
1592
1593            // Check if NFC is enabled
1594            if (!mIsNfcEnabled) {
1595                return null;
1596            }
1597
1598            /* find the tag in the hmap */
1599            tag = (NativeNfcTag) findObject(nativeHandle);
1600            if (tag != null) {
1601                response = tag.transceive(data, raw);
1602                return response;
1603            }
1604            return null;
1605        }
1606
1607        @Override
1608        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1609            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1610
1611            NativeNfcTag tag;
1612
1613            // Check if NFC is enabled
1614            if (!mIsNfcEnabled) {
1615                return null;
1616            }
1617
1618            /* find the tag in the hmap */
1619            tag = (NativeNfcTag) findObject(nativeHandle);
1620            if (tag != null) {
1621                byte[] buf = tag.read();
1622                if (buf == null)
1623                    return null;
1624
1625                /* Create an NdefMessage */
1626                try {
1627                    return new NdefMessage(buf);
1628                } catch (FormatException e) {
1629                    return null;
1630                }
1631            }
1632            return null;
1633        }
1634
1635        @Override
1636        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1637            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1638
1639            NativeNfcTag tag;
1640
1641            // Check if NFC is enabled
1642            if (!mIsNfcEnabled) {
1643                return ErrorCodes.ERROR_NOT_INITIALIZED;
1644            }
1645
1646            /* find the tag in the hmap */
1647            tag = (NativeNfcTag) findObject(nativeHandle);
1648            if (tag == null) {
1649                return ErrorCodes.ERROR_IO;
1650            }
1651
1652            if (tag.write(msg.toByteArray())) {
1653                return ErrorCodes.SUCCESS;
1654            }
1655            else {
1656                return ErrorCodes.ERROR_IO;
1657            }
1658
1659        }
1660
1661        @Override
1662        public int getLastError(int nativeHandle) throws RemoteException {
1663            return(mManager.doGetLastError());
1664        }
1665
1666        @Override
1667        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
1668            throw new UnsupportedOperationException();
1669        }
1670
1671        @Override
1672        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
1673            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1674
1675            NativeNfcTag tag;
1676
1677            // Check if NFC is enabled
1678            if (!mIsNfcEnabled) {
1679                return ErrorCodes.ERROR_NOT_INITIALIZED;
1680            }
1681
1682            /* find the tag in the hmap */
1683            tag = (NativeNfcTag) findObject(nativeHandle);
1684            if (tag == null) {
1685                return ErrorCodes.ERROR_IO;
1686            }
1687
1688            if (tag.makeReadonly()) {
1689                return ErrorCodes.SUCCESS;
1690            }
1691            else {
1692                return ErrorCodes.ERROR_IO;
1693            }
1694        }
1695
1696        @Override
1697        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
1698            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1699
1700            NativeNfcTag tag;
1701
1702            // Check if NFC is enabled
1703            if (!mIsNfcEnabled) {
1704                return ErrorCodes.ERROR_NOT_INITIALIZED;
1705            }
1706
1707            /* find the tag in the hmap */
1708            tag = (NativeNfcTag) findObject(nativeHandle);
1709            if (tag == null) {
1710                return ErrorCodes.ERROR_IO;
1711            }
1712
1713            if (tag.formatNdef(key)) {
1714                return ErrorCodes.SUCCESS;
1715            }
1716            else {
1717                return ErrorCodes.ERROR_IO;
1718            }
1719        }
1720
1721
1722    };
1723
1724    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1725
1726        @Override
1727        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1728            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1729
1730            NativeP2pDevice device;
1731
1732            // Check if NFC is enabled
1733            if (!mIsNfcEnabled) {
1734                return null;
1735            }
1736
1737            /* find the device in the hmap */
1738            device = (NativeP2pDevice) findObject(nativeHandle);
1739            if (device != null) {
1740                byte[] buff = device.getGeneralBytes();
1741                if (buff == null)
1742                    return null;
1743                return buff;
1744            }
1745            return null;
1746        }
1747
1748        @Override
1749        public int getMode(int nativeHandle) throws RemoteException {
1750            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1751
1752            NativeP2pDevice device;
1753
1754            // Check if NFC is enabled
1755            if (!mIsNfcEnabled) {
1756                return ErrorCodes.ERROR_NOT_INITIALIZED;
1757            }
1758
1759            /* find the device in the hmap */
1760            device = (NativeP2pDevice) findObject(nativeHandle);
1761            if (device != null) {
1762                return device.getMode();
1763            }
1764            return ErrorCodes.ERROR_INVALID_PARAM;
1765        }
1766
1767        @Override
1768        public byte[] receive(int nativeHandle) throws RemoteException {
1769            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1770
1771            NativeP2pDevice device;
1772
1773            // Check if NFC is enabled
1774            if (!mIsNfcEnabled) {
1775                return null;
1776            }
1777
1778            /* find the device in the hmap */
1779            device = (NativeP2pDevice) findObject(nativeHandle);
1780            if (device != null) {
1781                byte[] buff = device.doReceive();
1782                if (buff == null)
1783                    return null;
1784                return buff;
1785            }
1786            /* Restart polling loop for notification */
1787            maybeEnableDiscovery();
1788            return null;
1789        }
1790
1791        @Override
1792        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1793            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1794
1795            NativeP2pDevice device;
1796            boolean isSuccess = false;
1797
1798            // Check if NFC is enabled
1799            if (!mIsNfcEnabled) {
1800                return isSuccess;
1801            }
1802
1803            /* find the device in the hmap */
1804            device = (NativeP2pDevice) findObject(nativeHandle);
1805            if (device != null) {
1806                isSuccess = device.doSend(data);
1807            }
1808            return isSuccess;
1809        }
1810    };
1811
1812    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1813
1814        @Override
1815        public int connect(int nativeHandle) throws RemoteException {
1816            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1817
1818            NativeP2pDevice device;
1819
1820            // Check if NFC is enabled
1821            if (!mIsNfcEnabled) {
1822                return ErrorCodes.ERROR_NOT_INITIALIZED;
1823            }
1824
1825            /* find the device in the hmap */
1826            device = (NativeP2pDevice) findObject(nativeHandle);
1827            if (device != null) {
1828                if (device.doConnect()) {
1829                    return ErrorCodes.SUCCESS;
1830                }
1831            }
1832            return ErrorCodes.ERROR_CONNECT;
1833        }
1834
1835        @Override
1836        public boolean disconnect(int nativeHandle) throws RemoteException {
1837            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1838
1839            NativeP2pDevice device;
1840            boolean isSuccess = false;
1841
1842            // Check if NFC is enabled
1843            if (!mIsNfcEnabled) {
1844                return isSuccess;
1845            }
1846
1847            /* find the device in the hmap */
1848            device = (NativeP2pDevice) findObject(nativeHandle);
1849            if (device != null) {
1850                if (isSuccess = device.doDisconnect()) {
1851                    /* remove the device from the hmap */
1852                    unregisterObject(nativeHandle);
1853                    /* Restart polling loop for notification */
1854                    maybeEnableDiscovery();
1855                }
1856            }
1857            return isSuccess;
1858
1859        }
1860
1861        @Override
1862        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1863            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1864
1865            NativeP2pDevice device;
1866
1867            // Check if NFC is enabled
1868            if (!mIsNfcEnabled) {
1869                return null;
1870            }
1871
1872            /* find the device in the hmap */
1873            device = (NativeP2pDevice) findObject(nativeHandle);
1874            if (device != null) {
1875                byte[] buff = device.getGeneralBytes();
1876                if (buff == null)
1877                    return null;
1878                return buff;
1879            }
1880            return null;
1881        }
1882
1883        @Override
1884        public int getMode(int nativeHandle) throws RemoteException {
1885            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1886
1887            NativeP2pDevice device;
1888
1889            // Check if NFC is enabled
1890            if (!mIsNfcEnabled) {
1891                return ErrorCodes.ERROR_NOT_INITIALIZED;
1892            }
1893
1894            /* find the device in the hmap */
1895            device = (NativeP2pDevice) findObject(nativeHandle);
1896            if (device != null) {
1897                return device.getMode();
1898            }
1899            return ErrorCodes.ERROR_INVALID_PARAM;
1900        }
1901
1902        @Override
1903        public byte[] transceive(int nativeHandle, byte[] data)
1904                throws RemoteException {
1905            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1906
1907            NativeP2pDevice device;
1908
1909            // Check if NFC is enabled
1910            if (!mIsNfcEnabled) {
1911                return null;
1912            }
1913
1914            /* find the device in the hmap */
1915            device = (NativeP2pDevice) findObject(nativeHandle);
1916            if (device != null) {
1917                byte[] buff = device.doTransceive(data);
1918                if (buff == null)
1919                    return null;
1920                return buff;
1921            }
1922            return null;
1923        }
1924    };
1925
1926    private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() {
1927
1928        public int openSecureElementConnection() throws RemoteException {
1929            Log.d(TAG, "openSecureElementConnection");
1930            int handle;
1931
1932            // Check if NFC is enabled
1933            if (!mIsNfcEnabled) {
1934                return 0;
1935            }
1936
1937            // Check in an open is already pending
1938            if (mOpenSmxPending) {
1939                return 0;
1940            }
1941
1942            handle = mSecureElement.doOpenSecureElementConnection();
1943
1944            if (handle == 0) {
1945                mOpenSmxPending = false;
1946            } else {
1947                mSecureElementHandle = handle;
1948
1949                /* Start timer */
1950                mTimerOpenSmx = new Timer();
1951                mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
1952
1953                /* Update state */
1954                isOpened = true;
1955                isClosed = false;
1956                mOpenSmxPending = true;
1957            }
1958
1959            return handle;
1960        }
1961
1962        public int closeSecureElementConnection(int nativeHandle)
1963                throws RemoteException {
1964
1965            // Check if NFC is enabled
1966            if (!mIsNfcEnabled) {
1967                return ErrorCodes.ERROR_NOT_INITIALIZED;
1968            }
1969
1970            // Check if the SE connection is closed
1971            if (isClosed) {
1972                return -1;
1973            }
1974
1975            // Check if the SE connection is opened
1976            if (!isOpened) {
1977                return -1;
1978            }
1979
1980            if (mSecureElement.doDisconnect(nativeHandle)) {
1981
1982                /* Stop timer */
1983                mTimerOpenSmx.cancel();
1984
1985                /* Restart polling loop for notification */
1986                mManager.enableDiscovery(DISCOVERY_MODE_READER);
1987
1988                /* Update state */
1989                isOpened = false;
1990                isClosed = true;
1991                mOpenSmxPending = false;
1992
1993                return ErrorCodes.SUCCESS;
1994            } else {
1995
1996                /* Stop timer */
1997                mTimerOpenSmx.cancel();
1998
1999                /* Restart polling loop for notification */
2000                mManager.enableDiscovery(DISCOVERY_MODE_READER);
2001
2002                /* Update state */
2003                isOpened = false;
2004                isClosed = true;
2005                mOpenSmxPending = false;
2006
2007                return ErrorCodes.ERROR_DISCONNECT;
2008            }
2009        }
2010
2011        public int[] getSecureElementTechList(int nativeHandle)
2012                throws RemoteException {
2013            // Check if NFC is enabled
2014            if (!mIsNfcEnabled) {
2015                return null;
2016            }
2017
2018            // Check if the SE connection is closed
2019            if (isClosed) {
2020                return null;
2021            }
2022
2023            // Check if the SE connection is opened
2024            if (!isOpened) {
2025                return null;
2026            }
2027
2028            int[] techList = mSecureElement.doGetTechList(nativeHandle);
2029
2030            /* Stop and Restart timer */
2031            mTimerOpenSmx.cancel();
2032            mTimerOpenSmx = new Timer();
2033            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
2034
2035            return techList;
2036        }
2037
2038        public byte[] getSecureElementUid(int nativeHandle)
2039                throws RemoteException {
2040            byte[] uid;
2041
2042            // Check if NFC is enabled
2043            if (!mIsNfcEnabled) {
2044                return null;
2045            }
2046
2047            // Check if the SE connection is closed
2048            if (isClosed) {
2049                return null;
2050            }
2051
2052            // Check if the SE connection is opened
2053            if (!isOpened) {
2054                return null;
2055            }
2056
2057            uid = mSecureElement.doGetUid(nativeHandle);
2058
2059            /* Stop and Restart timer */
2060            mTimerOpenSmx.cancel();
2061            mTimerOpenSmx = new Timer();
2062            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
2063
2064            return uid;
2065        }
2066
2067        public byte[] exchangeAPDU(int nativeHandle, byte[] data)
2068                throws RemoteException {
2069            byte[] response;
2070
2071            // Check if NFC is enabled
2072            if (!mIsNfcEnabled) {
2073                return null;
2074            }
2075
2076            // Check if the SE connection is closed
2077            if (isClosed) {
2078                return null;
2079            }
2080
2081            // Check if the SE connection is opened
2082            if (!isOpened) {
2083                return null;
2084            }
2085
2086            response = mSecureElement.doTransceive(nativeHandle, data);
2087
2088            /* Stop and Restart timer */
2089            mTimerOpenSmx.cancel();
2090            mTimerOpenSmx = new Timer();
2091            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
2092
2093            return response;
2094
2095        }
2096    };
2097
2098    class TimerOpenSecureElement extends TimerTask {
2099
2100        @Override
2101        public void run() {
2102            if (mSecureElementHandle != 0) {
2103                Log.d(TAG, "Open SMX timer expired");
2104                try {
2105                    mSecureElementService
2106                            .closeSecureElementConnection(mSecureElementHandle);
2107                } catch (RemoteException e) {
2108                }
2109            }
2110
2111        }
2112
2113    }
2114
2115    private boolean _enable(boolean oldEnabledState) {
2116        boolean isSuccess = mManager.initialize();
2117        if (isSuccess) {
2118            applyProperties();
2119
2120            /* Check Secure Element setting */
2121            mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
2122                    SECURE_ELEMENT_ON_DEFAULT);
2123
2124            if (mNfcSecureElementState) {
2125                int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
2126                        SECURE_ELEMENT_ID_DEFAULT);
2127                int[] Se_list = mManager.doGetSecureElementList();
2128                if (Se_list != null) {
2129                    for (int i = 0; i < Se_list.length; i++) {
2130                        if (Se_list[i] == secureElementId) {
2131                            mManager.doSelectSecureElement(Se_list[i]);
2132                            mSelectedSeId = Se_list[i];
2133                            break;
2134                        }
2135                    }
2136                }
2137            }
2138
2139            mIsNfcEnabled = true;
2140
2141            /* Start polling loop */
2142            maybeEnableDiscovery();
2143
2144            /* bring up the my tag server */
2145            mMyTagServer.start();
2146
2147        } else {
2148            mIsNfcEnabled = false;
2149        }
2150
2151        updateNfcOnSetting(oldEnabledState);
2152
2153        return isSuccess;
2154    }
2155
2156    /** Enable active tag discovery if screen is on and NFC is enabled */
2157    private synchronized void maybeEnableDiscovery() {
2158        if (mScreenOn && mIsNfcEnabled) {
2159            mManager.enableDiscovery(DISCOVERY_MODE_READER);
2160        }
2161    }
2162
2163    /** Disable active tag discovery if necessary */
2164    private synchronized void maybeDisableDiscovery() {
2165        if (mIsNfcEnabled) {
2166            mManager.disableDiscovery();
2167        }
2168    }
2169
2170    private void applyProperties() {
2171        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2172        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2173        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2174        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2175        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2176                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2177        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2178                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2179        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2180                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2181        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2182                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2183        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2184                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2185     }
2186
2187    private void updateNfcOnSetting(boolean oldEnabledState) {
2188        int state;
2189
2190        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
2191        mPrefsEditor.apply();
2192
2193        synchronized(this) {
2194            if (oldEnabledState != mIsNfcEnabled) {
2195                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
2196                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2197                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
2198                mContext.sendBroadcast(intent);
2199            }
2200
2201            if (mIsNfcEnabled) {
2202
2203                Context context = getApplicationContext();
2204
2205                // Set this to null by default. If there isn't a tag on disk
2206                // or if there was an error reading the tag then this will cause
2207                // the status bar icon to be removed.
2208                NdefMessage myTag = null;
2209
2210                FileInputStream input = null;
2211
2212                try {
2213                    input = context.openFileInput(MY_TAG_FILE_NAME);
2214                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
2215
2216                    byte[] buffer = new byte[4096];
2217                    int read = 0;
2218                    while ((read = input.read(buffer)) > 0) {
2219                        bytes.write(buffer, 0, read);
2220                    }
2221
2222                    myTag = new NdefMessage(bytes.toByteArray());
2223                } catch (FileNotFoundException e) {
2224                    // Ignore.
2225                } catch (IOException e) {
2226                    Log.e(TAG, "Could not read mytag file: ", e);
2227                    context.deleteFile(MY_TAG_FILE_NAME);
2228                } catch (FormatException e) {
2229                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
2230                    context.deleteFile(MY_TAG_FILE_NAME);
2231                } finally {
2232                    try {
2233                        if (input != null) {
2234                            input.close();
2235                        }
2236                    } catch (IOException e) {
2237                        // Ignore
2238                    }
2239                }
2240
2241                try {
2242                    mNfcAdapter.localSet(myTag);
2243                } catch (RemoteException e) {
2244                    // Ignore
2245                }
2246            } else {
2247                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
2248            }
2249        }
2250    }
2251
2252    // Reset all internals
2253    private synchronized void reset() {
2254        // TODO: none of these appear to be synchronized but are
2255        // read/written from different threads (notably Binder threads)...
2256
2257        // Clear tables
2258        mObjectMap.clear();
2259        mSocketMap.clear();
2260        mRegisteredSocketList.clear();
2261
2262        // Reset variables
2263        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2264        mNbSocketCreated = 0;
2265        mIsNfcEnabled = false;
2266        mSelectedSeId = 0;
2267    }
2268
2269    private synchronized Object findObject(int key) {
2270        Object device = null;
2271
2272        device = mObjectMap.get(key);
2273        if (device == null) {
2274            Log.w(TAG, "Handle not found !");
2275        }
2276
2277        return device;
2278    }
2279
2280    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2281        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2282    }
2283
2284    synchronized void unregisterObject(int handle) {
2285        mObjectMap.remove(handle);
2286    }
2287
2288    private synchronized Object findSocket(int key) {
2289        Object socket = null;
2290
2291        socket = mSocketMap.get(key);
2292
2293        return socket;
2294    }
2295
2296    private void RemoveSocket(int key) {
2297        mSocketMap.remove(key);
2298    }
2299
2300    private boolean CheckSocketSap(int sap) {
2301        /* List of sockets registered */
2302        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2303
2304        while (it.hasNext()) {
2305            RegisteredSocket registeredSocket = it.next();
2306
2307            if (sap == registeredSocket.mSap) {
2308                /* SAP already used */
2309                return false;
2310            }
2311        }
2312        return true;
2313    }
2314
2315    private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
2316
2317        if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) {
2318            return false;
2319        }
2320        return true;
2321    }
2322
2323    private boolean CheckSocketServiceName(String sn) {
2324
2325        /* List of sockets registered */
2326        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2327
2328        while (it.hasNext()) {
2329            RegisteredSocket registeredSocket = it.next();
2330
2331            if (sn.equals(registeredSocket.mServiceName)) {
2332                /* Service Name already used */
2333                return false;
2334            }
2335        }
2336        return true;
2337    }
2338
2339    private void RemoveRegisteredSocket(int nativeHandle) {
2340        /* check if sockets are registered */
2341        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2342
2343        while (it.hasNext()) {
2344            RegisteredSocket registeredSocket = it.next();
2345            if (registeredSocket.mHandle == nativeHandle) {
2346                /* remove the registered socket from the list */
2347                it.remove();
2348                if (DBG) Log.d(TAG, "socket removed");
2349            }
2350        }
2351    }
2352
2353    /*
2354     * RegisteredSocket class to store the creation request of socket until the
2355     * LLCP link in not activated
2356     */
2357    private class RegisteredSocket {
2358        private final int mType;
2359
2360        private final int mHandle;
2361
2362        private final int mSap;
2363
2364        private int mMiu;
2365
2366        private int mRw;
2367
2368        private String mServiceName;
2369
2370        private int mlinearBufferLength;
2371
2372        RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
2373                int linearBufferLength) {
2374            mType = type;
2375            mHandle = handle;
2376            mSap = sap;
2377            mServiceName = sn;
2378            mRw = rw;
2379            mMiu = miu;
2380            mlinearBufferLength = linearBufferLength;
2381        }
2382
2383        RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
2384            mType = type;
2385            mHandle = handle;
2386            mSap = sap;
2387            mRw = rw;
2388            mMiu = miu;
2389            mlinearBufferLength = linearBufferLength;
2390        }
2391
2392        RegisteredSocket(int type, int handle, int sap) {
2393            mType = type;
2394            mHandle = handle;
2395            mSap = sap;
2396        }
2397    }
2398
2399    /** For use by code in this process */
2400    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2401        try {
2402            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
2403            if (ErrorCodes.isError(handle)) {
2404                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
2405                return null;
2406            }
2407            return new LlcpSocket(mLlcpSocket, handle);
2408        } catch (RemoteException e) {
2409            // This will never happen since the code is calling into it's own process
2410            throw new IllegalStateException("unable to talk to myself", e);
2411        }
2412    }
2413
2414    /** For use by code in this process */
2415    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2416            int linearBufferLength) {
2417        try {
2418            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
2419            if (ErrorCodes.isError(handle)) {
2420                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
2421                return null;
2422            }
2423            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2424        } catch (RemoteException e) {
2425            // This will never happen since the code is calling into it's own process
2426            throw new IllegalStateException("unable to talk to myself", e);
2427        }
2428    }
2429
2430    private void activateLlcpLink() {
2431        /* check if sockets are registered */
2432        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2433
2434        if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
2435
2436        /* Mark the link state */
2437        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED;
2438
2439        while (it.hasNext()) {
2440            RegisteredSocket registeredSocket = it.next();
2441
2442            switch (registeredSocket.mType) {
2443            case LLCP_SERVICE_SOCKET_TYPE:
2444                if (DBG) Log.d(TAG, "Registered Llcp Service Socket");
2445                if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName);
2446                NativeLlcpServiceSocket serviceSocket;
2447
2448                serviceSocket = mManager.doCreateLlcpServiceSocket(
2449                        registeredSocket.mSap, registeredSocket.mServiceName,
2450                        registeredSocket.mMiu, registeredSocket.mRw,
2451                        registeredSocket.mlinearBufferLength);
2452
2453                if (serviceSocket != null) {
2454                    if (DBG) Log.d(TAG, "service socket created");
2455                    /* Add the socket into the socket map */
2456                    synchronized(NfcService.this) {
2457                        mSocketMap.put(registeredSocket.mHandle, serviceSocket);
2458                    }
2459                } else {
2460                    Log.d(TAG, "FAILED to create service socket");
2461                    /* socket creation error - update the socket
2462                     * handle counter */
2463                    mGeneratedSocketHandle -= 1;
2464                }
2465
2466                // NOTE: don't remove this socket from the registered sockets list.
2467                // If it's removed it won't be created the next time an LLCP
2468                // connection is activated and the server won't be found.
2469                break;
2470
2471            case LLCP_SOCKET_TYPE:
2472                if (DBG) Log.d(TAG, "Registered Llcp Socket");
2473                NativeLlcpSocket clientSocket;
2474                clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
2475                        registeredSocket.mMiu, registeredSocket.mRw,
2476                        registeredSocket.mlinearBufferLength);
2477                if (clientSocket != null) {
2478                    if (DBG) Log.d(TAG, "socket created");
2479                    /* Add the socket into the socket map */
2480                    synchronized(NfcService.this) {
2481                        mSocketMap.put(registeredSocket.mHandle, clientSocket);
2482                    }
2483                } else {
2484                    Log.d(TAG, "FAILED to create service socket");
2485                    /* socket creation error - update the socket
2486                     * handle counter */
2487                    mGeneratedSocketHandle -= 1;
2488                }
2489                // This socket has been created, remove it from the registered sockets list.
2490                it.remove();
2491                break;
2492
2493            case LLCP_CONNECTIONLESS_SOCKET_TYPE:
2494                if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket");
2495                NativeLlcpConnectionlessSocket connectionlessSocket;
2496                connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket(
2497                        registeredSocket.mSap);
2498                if (connectionlessSocket != null) {
2499                    if (DBG) Log.d(TAG, "connectionless socket created");
2500                    /* Add the socket into the socket map */
2501                    synchronized(NfcService.this) {
2502                        mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
2503                    }
2504                } else {
2505                    Log.d(TAG, "FAILED to create service socket");
2506                    /* socket creation error - update the socket
2507                     * handle counter */
2508                    mGeneratedSocketHandle -= 1;
2509                }
2510                // This socket has been created, remove it from the registered sockets list.
2511                it.remove();
2512                break;
2513            }
2514        }
2515
2516        /* Broadcast Intent Link LLCP activated */
2517        Intent LlcpLinkIntent = new Intent();
2518        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2519
2520        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2521                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2522
2523        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
2524        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2525    }
2526
2527    public void sendMockNdefTag(NdefMessage msg) {
2528        sendMessage(MSG_MOCK_NDEF, msg);
2529    }
2530
2531    void sendMessage(int what, Object obj) {
2532        Message msg = mHandler.obtainMessage();
2533        msg.what = what;
2534        msg.obj = obj;
2535        mHandler.sendMessage(msg);
2536    }
2537
2538    final class NfcServiceHandler extends Handler {
2539
2540        public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
2541            // Try to find NDEF on any of the technologies.
2542            int[] technologies = nativeTag.getTechList();
2543            int[] handles = nativeTag.getHandleList();
2544            int techIndex = 0;
2545            int lastHandleScanned = 0;
2546            boolean ndefFoundAndConnected = false;
2547            NdefMessage[] ndefMsgs = null;
2548
2549            while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
2550                if (handles[techIndex] != lastHandleScanned) {
2551                    // We haven't seen this handle yet, connect and checkndef
2552                    if (nativeTag.connect(technologies[techIndex])) {
2553                        int[] ndefinfo = new int[2];
2554                        if (nativeTag.checkNdef(ndefinfo)) {
2555                            ndefFoundAndConnected = true;
2556                            boolean generateEmptyNdef = false;
2557
2558                            int supportedNdefLength = ndefinfo[0];
2559                            int cardState = ndefinfo[1];
2560                            byte[] buff = nativeTag.read();
2561                            if (buff != null) {
2562                                ndefMsgs = new NdefMessage[1];
2563                                try {
2564                                    ndefMsgs[0] = new NdefMessage(buff);
2565                                    nativeTag.addNdefTechnology(ndefMsgs[0],
2566                                            nativeTag.getConnectedHandle(),
2567                                            nativeTag.getConnectedLibNfcType(),
2568                                            nativeTag.getConnectedTechnology(),
2569                                            supportedNdefLength, cardState);
2570                                    nativeTag.reconnect();
2571                                } catch (FormatException e) {
2572                                   // Create an intent anyway, without NDEF messages
2573                                   generateEmptyNdef = true;
2574                                }
2575                            } else {
2576                                generateEmptyNdef = true;
2577                            }
2578
2579                           if (generateEmptyNdef) {
2580                               ndefMsgs = new NdefMessage[] { };
2581                               nativeTag.addNdefTechnology(null,
2582                                       nativeTag.getConnectedHandle(),
2583                                       nativeTag.getConnectedLibNfcType(),
2584                                       nativeTag.getConnectedTechnology(),
2585                                       supportedNdefLength, cardState);
2586                               nativeTag.reconnect();
2587                           }
2588                        } // else, no NDEF on this tech, continue loop
2589                    } else {
2590                        // Connect failed, tag maybe lost. Try next handle
2591                        // anyway.
2592                    }
2593                }
2594                lastHandleScanned = handles[techIndex];
2595                techIndex++;
2596            }
2597
2598            return ndefMsgs;
2599        }
2600
2601        @Override
2602        public void handleMessage(Message msg) {
2603           switch (msg.what) {
2604           case MSG_MOCK_NDEF: {
2605               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2606               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2607                       new int[] { },
2608                       new Bundle[] { });
2609               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
2610               Log.d(TAG, tag.toString());
2611               dispatchTag(tag, new NdefMessage[] { ndefMsg });
2612               break;
2613           }
2614
2615           case MSG_NDEF_TAG:
2616               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2617               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2618               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2619
2620               if (ndefMsgs != null) {
2621                   dispatchNativeTag(nativeTag, ndefMsgs);
2622               } else {
2623                   // No ndef found or connect failed, just try to reconnect and dispatch
2624                   if (nativeTag.reconnect()) {
2625                       dispatchNativeTag(nativeTag, null);
2626                   } else {
2627                       Log.w(TAG, "Failed to connect to tag");
2628                       nativeTag.disconnect();
2629                   }
2630               }
2631               break;
2632
2633           case MSG_CARD_EMULATION:
2634               if (DBG) Log.d(TAG, "Card Emulation message");
2635               byte[] aid = (byte[]) msg.obj;
2636               /* Send broadcast ordered */
2637               Intent TransactionIntent = new Intent();
2638               TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
2639               TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
2640               if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
2641               mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
2642               break;
2643
2644           case MSG_LLCP_LINK_ACTIVATION:
2645               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2646
2647               Log.d(TAG, "LLCP Activation message");
2648
2649               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2650                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2651                   if (device.doConnect()) {
2652                       /* Check Llcp compliancy */
2653                       if (mManager.doCheckLlcp()) {
2654                           /* Activate Llcp Link */
2655                           if (mManager.doActivateLlcp()) {
2656                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2657                               activateLlcpLink();
2658                           } else {
2659                               /* should not happen */
2660                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2661                               device.doDisconnect();
2662                           }
2663
2664                       } else {
2665                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2666                           device.doDisconnect();
2667                       }
2668                   } else {
2669                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop.");
2670                       device.doDisconnect();
2671                   }
2672
2673               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2674                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2675                   /* Check Llcp compliancy */
2676                   if (mManager.doCheckLlcp()) {
2677                       /* Activate Llcp Link */
2678                       if (mManager.doActivateLlcp()) {
2679                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2680                           activateLlcpLink();
2681                      }
2682                   } else {
2683                       Log.w(TAG, "checkLlcp failed");
2684                   }
2685               }
2686               break;
2687
2688           case MSG_LLCP_LINK_DEACTIVATED:
2689               device = (NativeP2pDevice) msg.obj;
2690
2691               /* Mark the link state */
2692               mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2693
2694               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2695               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2696                   if (DBG) Log.d(TAG, "disconnecting from target");
2697                   /* Restart polling loop */
2698                   device.doDisconnect();
2699               } else {
2700                   if (DBG) Log.d(TAG, "not disconnecting from initiator");
2701               }
2702
2703               /* Broadcast Intent Link LLCP activated */
2704               Intent LlcpLinkIntent = new Intent();
2705               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2706               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2707                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2708               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2709               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2710               break;
2711
2712           case MSG_TARGET_DESELECTED:
2713               /* Broadcast Intent Target Deselected */
2714               if (DBG) Log.d(TAG, "Target Deselected");
2715               Intent TargetDeselectedIntent = new Intent();
2716               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2717               if (DBG) Log.d(TAG, "Broadcasting Intent");
2718               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2719               break;
2720
2721           case MSG_SHOW_MY_TAG_ICON: {
2722               StatusBarManager sb = (StatusBarManager) getSystemService(
2723                       Context.STATUS_BAR_SERVICE);
2724               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
2725               break;
2726           }
2727
2728           case MSG_HIDE_MY_TAG_ICON: {
2729               StatusBarManager sb = (StatusBarManager) getSystemService(
2730                       Context.STATUS_BAR_SERVICE);
2731               sb.removeIcon("nfc");
2732               break;
2733           }
2734
2735           case MSG_SE_FIELD_ACTIVATED:{
2736               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2737               Intent eventFieldOnIntent = new Intent();
2738               eventFieldOnIntent.setAction(NfcAdapter.ACTION_RF_FIELD_ON_DETECTED);
2739               if (DBG) Log.d(TAG, "Broadcasting Intent");
2740               mContext.sendBroadcast(eventFieldOnIntent, NFC_PERM);
2741               break;
2742           }
2743
2744           case MSG_SE_FIELD_DEACTIVATED:{
2745               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2746               Intent eventFieldOffIntent = new Intent();
2747               eventFieldOffIntent.setAction(NfcAdapter.ACTION_RF_FIELD_OFF_DETECTED);
2748               if (DBG) Log.d(TAG, "Broadcasting Intent");
2749               mContext.sendBroadcast(eventFieldOffIntent, NFC_PERM);
2750               break;
2751           }
2752
2753           default:
2754               Log.e(TAG, "Unknown message received");
2755               break;
2756           }
2757        }
2758
2759        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
2760            Intent intent = new Intent(action);
2761            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2762            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2763            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2764            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2765            return intent;
2766        }
2767
2768        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
2769            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
2770                    nativeTag.getTechExtras(), nativeTag.getHandle());
2771            if (dispatchTag(tag, msgs)) {
2772                registerTagObject(nativeTag);
2773            } else {
2774                nativeTag.disconnect();
2775            }
2776        }
2777
2778        public byte[] concat(byte[]... arrays) {
2779            int length = 0;
2780            for (byte[] array : arrays) {
2781                length += array.length;
2782            }
2783            byte[] result = new byte[length];
2784            int pos = 0;
2785            for (byte[] array : arrays) {
2786                System.arraycopy(array, 0, result, pos, array.length);
2787                pos += array.length;
2788            }
2789            return result;
2790        }
2791
2792        private Uri parseWellKnownUriRecord(NdefRecord record) {
2793            byte[] payload = record.getPayload();
2794
2795            /*
2796             * payload[0] contains the URI Identifier Code, per the
2797             * NFC Forum "URI Record Type Definition" section 3.2.2.
2798             *
2799             * payload[1]...payload[payload.length - 1] contains the rest of
2800             * the URI.
2801             */
2802            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
2803            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
2804                    Arrays.copyOfRange(payload, 1, payload.length));
2805            return Uri.parse(new String(fullUri, Charsets.UTF_8));
2806        }
2807
2808        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
2809            short tnf = record.getTnf();
2810            byte[] type = record.getType();
2811            switch (tnf) {
2812                case NdefRecord.TNF_MIME_MEDIA: {
2813                    intent.setType(new String(type, Charsets.US_ASCII));
2814                    return true;
2815                }
2816                case NdefRecord.TNF_ABSOLUTE_URI: {
2817                    intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
2818                    return true;
2819                }
2820                case NdefRecord.TNF_WELL_KNOWN: {
2821                    if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
2822                        intent.setType("text/plain");
2823                        return true;
2824                    } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
2825                        // Parse the smart poster looking for the URI
2826                        try {
2827                            NdefMessage msg = new NdefMessage(record.getPayload());
2828                            for (NdefRecord subRecord : msg.getRecords()) {
2829                                if (subRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN
2830                                        && Arrays.equals(subRecord.getType(), NdefRecord.RTD_URI)) {
2831                                    intent.setData(parseWellKnownUriRecord(subRecord));
2832                                    return true;
2833                                }
2834                            }
2835                        } catch (FormatException e) {
2836                            return false;
2837                        }
2838                    } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
2839                        intent.setData(parseWellKnownUriRecord(record));
2840                        return true;
2841                    }
2842                    return false;
2843                }
2844            }
2845            return false;
2846        }
2847
2848        private Uri buildTechListUri(Tag tag) {
2849            int[] techList = tag.getTechnologyList();
2850            Arrays.sort(techList);
2851            Uri.Builder builder = new Uri.Builder();
2852            builder.scheme("vnd.android.nfc").authority("tag");
2853            for (int tech : techList) {
2854                builder.appendPath(Integer.toString(tech));
2855            }
2856            builder.appendPath("");
2857            return builder.build();
2858        }
2859
2860        /** Returns false if no activities were found to dispatch to */
2861        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
2862            if (DBG) {
2863                Log.d(TAG, "Dispatching tag");
2864                Log.d(TAG, tag.toString());
2865            }
2866
2867            IntentFilter[] overrideFilters;
2868            PendingIntent overrideIntent;
2869            synchronized (mNfcAdapter) {
2870                overrideFilters = mDispatchOverrideFilters;
2871                overrideIntent = mDispatchOverrideIntent;
2872            }
2873
2874            // First look for dispatch overrides
2875            if (overrideFilters != null && overrideIntent != null) {
2876                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
2877                try {
2878                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters)) {
2879                        if (DBG) Log.d(TAG, "Dispatched to override");
2880                        return true;
2881                    }
2882                    Log.w(TAG, "Dispatch override registered, but no filters matched");
2883                } catch (CanceledException e) {
2884                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
2885                    synchronized (mNfcAdapter) {
2886                        mDispatchOverrideFilters = null;
2887                        mDispatchOverrideIntent = null;
2888                    }
2889                }
2890            }
2891
2892            // Try a standard dispatch
2893            try {
2894                return dispatchTagInternal(tag, msgs, null, null);
2895            } catch (CanceledException e) {
2896                Log.e(TAG, "CanceledException unexpected here", e);
2897                return false;
2898            }
2899        }
2900
2901        // Dispatch to either an override pending intent or a standard startActivity()
2902        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
2903                PendingIntent overrideIntent, IntentFilter[] overrideFilters)
2904                throws CanceledException{
2905            Intent intent;
2906            if (msgs != null && msgs.length > 0) {
2907                NdefMessage msg = msgs[0];
2908                NdefRecord[] records = msg.getRecords();
2909                if (records.length > 0) {
2910                    // Found valid NDEF data, try to dispatch that first
2911                    NdefRecord record = records[0];
2912
2913                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
2914                    setTypeOrDataFromNdef(intent, record);
2915
2916                    if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
2917                        // If an activity is found then skip further dispatching
2918                        return true;
2919                    } else {
2920                        if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
2921                    }
2922                }
2923            }
2924
2925            // Try the technology specific dispatch
2926            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
2927            intent.setData(buildTechListUri(tag));
2928            if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
2929                return true;
2930            } else {
2931                if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
2932            }
2933
2934            // Try the generic intent
2935            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
2936            if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
2937                return true;
2938            } else {
2939                Log.e(TAG, "No tag fallback activity found for " + intent);
2940                return false;
2941            }
2942        }
2943
2944        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
2945                IntentFilter[] overrideFilters) throws CanceledException {
2946            if (overrideIntent != null) {
2947                for (IntentFilter filter : overrideFilters) {
2948                    if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
2949                        Log.i(TAG, "Dispatching to override intent " + overrideIntent);
2950                        overrideIntent.send(mContext, Activity.RESULT_OK, intent);
2951                        return true;
2952                    }
2953                }
2954                return false;
2955            } else {
2956                try {
2957                    mContext.startActivity(intent);
2958                    return true;
2959                } catch (ActivityNotFoundException e) {
2960                    return false;
2961                }
2962            }
2963        }
2964    }
2965
2966    private NfcServiceHandler mHandler = new NfcServiceHandler();
2967
2968    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2969        @Override
2970        protected Void doInBackground(Boolean... enable) {
2971            if (enable != null && enable.length > 0 && enable[0]) {
2972                synchronized (NfcService.this) {
2973                    mScreenOn = true;
2974                    maybeEnableDiscovery();
2975                }
2976            } else {
2977                mWakeLock.acquire();
2978                synchronized (NfcService.this) {
2979                    mScreenOn = false;
2980                    maybeDisableDiscovery();
2981                }
2982                mWakeLock.release();
2983            }
2984            return null;
2985        }
2986    }
2987
2988    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
2989        @Override
2990        public void onReceive(Context context, Intent intent) {
2991            if (intent.getAction().equals(
2992                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2993                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
2994
2995                /* Restart polling loop for notification */
2996                maybeEnableDiscovery();
2997
2998            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
2999                // Perform discovery enable in thread to protect against ANR when the
3000                // NFC stack wedges. This is *not* the correct way to fix this issue -
3001                // configuration of the local NFC adapter should be very quick and should
3002                // be safe on the main thread, and the NFC stack should not wedge.
3003                new EnableDisableDiscoveryTask().execute(new Boolean(true));
3004            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
3005                // Perform discovery disable in thread to protect against ANR when the
3006                // NFC stack wedges. This is *not* the correct way to fix this issue -
3007                // configuration of the local NFC adapter should be very quick and should
3008                // be safe on the main thread, and the NFC stack should not wedge.
3009                new EnableDisableDiscoveryTask().execute(new Boolean(false));
3010            }
3011        }
3012    };
3013}
3014