NfcService.java revision aae427142dc22e7e419c146bc7748d9daff518e8
1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License.
6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at
7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software
11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and
14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License.
15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellypackage com.android.nfc;
18f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpServiceSocket;
20d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpSocket;
2157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport com.android.nfc.mytag.MyTagClient;
2257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport com.android.nfc.mytag.MyTagServer;
23d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport android.app.StatusBarManager;
26b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
2713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
2813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
2913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
32f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
33f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
34f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
35f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
36f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
38f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
39f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
40f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
41f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
42f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport android.nfc.INfcSecureElement;
467c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
47b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
48b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
49b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
50533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
5213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
5657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
5757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
5857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
5957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
603ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
613ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.LinkedList;
623ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.ListIterator;
630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.Timer;
640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.TimerTask;
653ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
67ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
68fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
6957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
7057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
7113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
7213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
7313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
7413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
75d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
76fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
77f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
78f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
79bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
80bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
81bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
82bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
83bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
85f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
88f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
91f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
94f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
96e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
98f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
103f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
108f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
112f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
126a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
127f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Card Emulation Discovery mode for enableDiscovery() */
1320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
1350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_TYPE = 1;
1360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
1370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_NB_MAX = 5;  // Maximum number of socket managed
1380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_RW_MAX_VALUE = 15;  // Receive Window
139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
1460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
1500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
1520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
1540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
1560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
159b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
160b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
161b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
162b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
163b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
16457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
16557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
166b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
167b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
16874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
16974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mNbSocketCreated = 0;
17474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mSelectedSeId = 0;
1760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean mNfcSecureElementState;
177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    // Secure element
1790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private Timer mTimerOpenSmx;
1800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isClosed = false;
1810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isOpened = false;
1820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean mOpenSmxPending = false;
1830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
1840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private int mSecureElementHandle;
1850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
1872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
1882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
18965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
1902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
1912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
1920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private Context mContext;
1930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
1940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
1950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
196533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
19757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private MyTagServer mMyTagServer;
19857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private MyTagClient mMyTagClient;
199d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
200d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
201d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
202d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
203d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
204d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2082f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
212d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
213d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
2160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
21774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
21857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton        mMyTagServer = new MyTagServer();
21957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton        mMyTagClient = new MyTagClient(this);
22057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
2240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
226d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
228533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
22952028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
230533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
231533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
232d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
234eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
23565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
23665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
2370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
2380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
2430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
2440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
2480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
2490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
2532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
2542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
2550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
2560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
2593ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
2603ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
2614acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
262fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
264d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
2650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
2670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
2680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
2690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
2700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
275fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
2770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
278d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
2790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
280ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
2810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
2836f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
28457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mMyTagServer.stop();
2850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
286ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
2870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
2880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
2890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
2930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
297fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
299d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
300bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
3070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check nb socket created */
3090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
3100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store the socket handle */
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
3120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
3140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket;
3150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpConnectionlessSocket(sap);
3170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
3182f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
3192f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
3202f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
3210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3222f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
3232f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
3242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return sockeHandle;
326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    } else {
3270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
3280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
3310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
3320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
3340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
3350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
3380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
3400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
3410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
3420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
3430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
3460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
3470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
3480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
3490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
3542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
3552f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3572f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
3582f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
3592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
3600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
3610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(
3620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
3630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
3690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
3700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
3720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
3740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
3750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
380fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
3820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
383d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
384bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
3910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
3920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
3940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpServiceSocket socket;
3950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
3982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
3992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
4002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
4012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
4022f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
4032f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
4040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
4050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* socket creation error - update the socket handle counter */
4060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
4070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
4090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
4100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
4120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
4170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
4180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
4190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
4210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
4230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
4240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
4250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Service Name */
4280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketServiceName(sn)) {
4290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SERVICE_NAME_USED;
4300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check socket options */
4330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
4340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
4350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
43715151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                    NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw,
43815151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                            linearBufferLength);
4392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
4402f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
4412f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
4420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4432f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
4442f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
4452f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
4460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
4470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
4480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, sn, miu, rw, linearBufferLength);
4490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
4510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
4530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
4550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle += 1;
4560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
457ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
4580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
459f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
4610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
465fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
4670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
468d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
469bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
4760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
4780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
480ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "creating llcp socket while activated");
4810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket;
4820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
4840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
4862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
4872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
4882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
4892f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
4902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
4912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
4920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
4930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
4940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
4950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
4960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
4970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
4980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
5000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
5010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5026f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                        Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
5036f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton
5040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
5050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
5100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
5110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
5120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
514ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "registering llcp socket while not activated");
515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
5170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
5190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check Socket options */
5220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
5230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
5240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
525bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
5272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
5282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
5292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5312f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
5322f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
5332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
5340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
5350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
5360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, miu, rw, linearBufferLength);
5370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
5390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
5400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
5410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
5430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
5440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
5480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
551f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
552fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int deselectSecureElement() throws RemoteException {
554d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
559f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
560f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == 0) {
5620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NO_SE_CONNECTED;
563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
5640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doDeselectSecureElement(mSelectedSeId);
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = false;
5670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = 0;
5680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store preference */
5700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
5710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
5722f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
5730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
575f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
576f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
577fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
579d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
5810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
582bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
583fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
585d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
5870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
588f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
589fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
591d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
5930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
595fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
597d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
5990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
601fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
603d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
607fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
609d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public INfcSecureElement getNfcSecureElementInterface() {
6140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return mSecureElementService;
6160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
618fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
620d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
6390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
644f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
649fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int[] getSecureElementList() throws RemoteException {
651d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
652bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int[] list = null;
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mIsNfcEnabled == true) {
6550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                list = mManager.doGetSecureElementList();
6560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return list;
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
660fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getSelectedSecureElement() throws RemoteException {
662d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mSelectedSeId;
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
667fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
672fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void openTagConnection(Tag tag) throws RemoteException {
674b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: Remove obsolete code
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
677fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int selectSecureElement(int seId) throws RemoteException {
679d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
680f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == seId) {
6870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId != 0) {
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_CONNECTED;
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = seId;
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doSelectSecureElement(mSelectedSeId);
6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store */
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
7002f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = true;
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
708fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
710d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
7322f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
7462f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
7602f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
7742f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
7842f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
7942f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
8042f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
8142f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
8242f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
834f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
835d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
836d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
837d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
83857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
83957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
84057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
84157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
84257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
843d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
844d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
845d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
846d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
84757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
84857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
84957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
85057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
85157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
85257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
85357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
85457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
85557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
85657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
85757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
85857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
85957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
86057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
86157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
86257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
86357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
86457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
86657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
86757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
86857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
86957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
87057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
87157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
87257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
87357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
87457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
87557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
87657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
87757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
87857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
87957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
88057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
88157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
88257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
88357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
88457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
88557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
88657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
88757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
888d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
8890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
8920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CONNECT_FLAG = 0x01;
8940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CLOSE_FLAG   = 0x02;
8950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int RECV_FLAG    = 0x04;
8960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int SEND_FLAG    = 0x08;
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private int concurrencyFlags;
8990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private Object sync;
9000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
901fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
903d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
904bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
909f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
914f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
9170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
9180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
9190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Remove the socket closed from the hmap */
9200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        RemoveSocket(nativeHandle);
9210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Update mNbSocketCreated */
9220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mNbSocketCreated--;
9230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.SUCCESS;
9240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
9250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
9260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
9280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
9290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
9300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove registered socket from the list */
9320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveRegisteredSocket(nativeHandle);
9330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
9350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
944fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
946d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
947bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
95993915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
9600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
9610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
971fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
973d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
974bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
98693915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
998fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
1000d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1001bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1007f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
10090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
10100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
10140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1018fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1020d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1021bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
10330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1038fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1040d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1041bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1045f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1046f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1047f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1049f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
10530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1058fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1060d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1082fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1084d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
10940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1106fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1108d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int receiveLength = 0;
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
112128f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
11220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
112328f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1127fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1129d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
11430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
11440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
11450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
11500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
11530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
11550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1156fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1158d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
11690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
11700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
11710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
117293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
11730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
11740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
11750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
11762f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
11772f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(clientSocket.getHandle(), clientSocket);
11782f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
11792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return clientSocket.getHandle();
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
11820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
11830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
11840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
11890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1193fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1195d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
11990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
12030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1206f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            boolean closed = false;
12070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
12080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
12090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
12100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
12110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
1212f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                        closed = true;
12130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
12140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
1215f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    closed = true;
1216f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                }
1217f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            }
1218f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1219f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            // If the socket is closed remove it from the socket lists
1220f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            if (closed) {
1221f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
12220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
12230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
12240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
12260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
1227f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1228f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    /* Remove registered socket from the list */
1229f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    RemoveRegisteredSocket(nativeHandle);
12300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1237fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1239d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1240bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    isSuccess = socket.doClose();
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    if (isSuccess) {
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Remove the socket closed from the hmap */
1256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        RemoveSocket(nativeHandle);
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Update mNbSocketCreated */
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        mNbSocketCreated--;
1259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove the socket closed from the hmap */
1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveSocket(nativeHandle);
1263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove registered socket from the list */
1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveRegisteredSocket(nativeHandle);
1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Update mNbSocketCreated */
1268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    mNbSocketCreated--;
1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1273fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1275d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1276bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1293fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1295d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1296bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1318fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1320d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1321bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1347fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1349d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1350bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1361b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1362b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
136321545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1364b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
136765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1371fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int connect(int nativeHandle) throws RemoteException {
1373d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1374bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1384b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1385b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1387b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: register the tag as being locked rather than really connect
1388b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return ErrorCodes.SUCCESS;
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1391fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1392aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1393aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1394aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1395aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1396aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1397aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1398aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1399aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1400aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1401aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1402aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1403aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1404aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1405aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1406aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1407aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1408aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1409aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1410aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1411aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1412aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1413aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1414aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1415b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1416d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1417bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1424b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1426b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1430f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1431fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1444f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1450fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1451b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1452b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1453b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1454b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1455b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1456b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1457b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1458b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1459b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1460b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1461b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1462b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1463b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1464b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1465b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return tag.presenceCheck();
1466b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1467b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1468fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1477f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
14803ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14823ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1485f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1486f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1487fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
148897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data, boolean raw)
148997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1490d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1491bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1492f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1493f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1501f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
150397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                response = tag.transceive(data, raw);
1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return response;
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1507f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1509fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1510f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public NdefMessage read(int nativeHandle) throws RemoteException {
1511d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1512bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1514f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1521f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1522f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1523b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1526f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1528f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1535f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1537fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1538f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int write(int nativeHandle, NdefMessage msg) throws RemoteException {
1539d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1540bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1544f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1551f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1552f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1553f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1554b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1559f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1560f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1561f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1563fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1564f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1565f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // TODO Auto-generated method stub
15660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return 0;
1567f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1569fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getModeHint(int nativeHandle) throws RemoteException {
15710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // TODO Auto-generated method stub
15720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return 0;
1573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1574f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1575fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int makeReadOnly(int nativeHandle) throws RemoteException {
15770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // TODO Auto-generated method stub
15780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return 0;
1579f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15810aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
15820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
15830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
15860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
15880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
15890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
15900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
15930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
15950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15980aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
15990aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
16000aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16010aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
16020aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
16030aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16040aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
16050aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1606f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1608f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1610f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1611fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1613d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1616f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1621f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
16260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1632f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1633fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1635d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1636f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1638f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1649f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1650f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1651f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1652fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1654d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1657f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1662f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
16670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
167265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1675f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1676fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1678d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1687f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1698f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1699fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1701d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1704f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
17080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1709f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1719f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1720fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1722d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1723f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1726f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1737b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
173965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                    maybeEnableDiscovery();
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1741f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1743f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1745f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1746fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1748d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
17520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1755f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1756f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1767f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1768fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1770d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1771f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1773f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1777f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1778f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
17850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1786f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1787fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
178897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
178997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1790d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1791f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1793f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1797f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1798f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
18030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
18090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() {
18120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int openSecureElementConnection() throws RemoteException {
18140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            Log.d(TAG, "openSecureElementConnection");
18150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int handle;
18160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check in an open is already pending
18230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mOpenSmxPending) {
18240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            handle = mSecureElement.doOpenSecureElementConnection();
18280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (handle == 0) {
18300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
18320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mSecureElementHandle = handle;
18330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Start timer */
18350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx = new Timer();
18360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
18370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = true;
18400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = false;
18410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = true;
18420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return handle;
18450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int closeSecureElementConnection(int nativeHandle)
18480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
18490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_NOT_INITIALIZED;
18530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
18560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
18570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
18580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
18610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
18620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
18630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElement.doDisconnect(nativeHandle)) {
18660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
18680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
18690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
18710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
18720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
18750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
18760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.SUCCESS;
18790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
18800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
18820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
18830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
18850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
18860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
18890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
18900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_DISCONNECT;
18930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int[] getSecureElementTechList(int nativeHandle)
18970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
18980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int[] techList = mSecureElement.doGetTechList(nativeHandle);
19140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return techList;
19210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] getSecureElementUid(int nativeHandle)
19240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] uid;
19260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            uid = mSecureElement.doGetUid(nativeHandle);
19430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return uid;
19500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] exchangeAPDU(int nativeHandle, byte[] data)
19530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] response;
19550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            response = mSecureElement.doTransceive(nativeHandle, data);
19720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return response;
19790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
19820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    class TimerOpenSecureElement extends TimerTask {
19840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        @Override
19860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public void run() {
19870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElementHandle != 0) {
19880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                Log.d(TAG, "Open SMX timer expired");
19890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
19900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                    mSecureElementService
19910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                            .closeSecureElementConnection(mSecureElementHandle);
19920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                } catch (RemoteException e) {
19930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                }
19940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
19990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
20010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
20020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
2003f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly            applyProperties();
2004f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
20050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check Secure Element setting */
20060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
20070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    SECURE_ELEMENT_ON_DEFAULT);
2008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNfcSecureElementState) {
20100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
20110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        SECURE_ELEMENT_ID_DEFAULT);
20120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int[] Se_list = mManager.doGetSecureElementList();
20130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (Se_list != null) {
20140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    for (int i = 0; i < Se_list.length; i++) {
20150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        if (Se_list[i] == secureElementId) {
20160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mManager.doSelectSecureElement(Se_list[i]);
20170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mSelectedSeId = Se_list[i];
20180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            break;
20190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
20200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
20210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2022f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
202465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
202565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
202765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
202857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
202957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
203057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mMyTagServer.start();
203157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
20330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
2034f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
2037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
2039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
204165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Enable active tag discovery if screen is on and NFC is enabled */
204265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeEnableDiscovery() {
204365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mScreenOn && mIsNfcEnabled) {
204465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.enableDiscovery(DISCOVERY_MODE_READER);
204565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
204665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
204765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
204865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Disable active tag discovery if necessary */
204965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeDisableDiscovery() {
205065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mIsNfcEnabled) {
205165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.disableDiscovery();
205265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
205365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
205465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
2055f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2056f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2057f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2058f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2059f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2060f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2061f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2062f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2063f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2064f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2065f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2066f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2067f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2068f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2069f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2070f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2071f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
20720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
20730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        int state;
2074f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
20762f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
20770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
20782f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
20794acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
20802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
20814acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
20822f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
20832f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
20842f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
208557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
208657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
208757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
208857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
208957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
209057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
209157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
209257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
209357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
209457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
209557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
209657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
209757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
209857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
209957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
210057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
210157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
210257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
210357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
210457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
210557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
210657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
210757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
210857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
210957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
211057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
211157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
211257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
211357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
211457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
211557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
211657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
211757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
211857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
211957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
212057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
212157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
212257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
212357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
212457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
212557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
212657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
212757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
212857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
212957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
213057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
213157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
213257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
213357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
21340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
21382f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
213974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
214074180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mRegisteredSocketList.clear();
2146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mNbSocketCreated = 0;
2150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSelectedSeId = 0;
2152f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2166b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2167b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2168b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
21692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2170b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21732f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object socket = null;
2175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        socket = mSocketMap.get(key);
2177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return socket;
2179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketSap(int sap) {
2186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sap == registeredSocket.mSap) {
2193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* SAP already used */
2194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
2201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) {
2203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return false;
2204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketServiceName(String sn) {
2209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sn.equals(registeredSocket.mServiceName)) {
2217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Service Name already used */
2218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveRegisteredSocket(int nativeHandle) {
2225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* check if sockets are registered */
2226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (registeredSocket.mHandle == nativeHandle) {
2231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* remove the registered socket from the list */
2232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                it.remove();
2233ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "socket removed");
2234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    /*
2239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * RegisteredSocket class to store the creation request of socket until the
2240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * LLCP link in not activated
2241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     */
2242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private class RegisteredSocket {
2243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mType;
2244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mHandle;
2246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mSap;
2248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mMiu;
2250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mRw;
2252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private String mServiceName;
2254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mlinearBufferLength;
2256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
2258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                int linearBufferLength) {
2259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mServiceName = sn;
2263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
2269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap) {
2278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2284d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2285d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2286d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2287d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
22881be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22891be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22901be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22911be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2292d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2293d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2294d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2295d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2296d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2297d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2298d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2299d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2300d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2301d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2302d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2303d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
23041be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23051be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23061be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23071be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2308d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2309d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2310d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2311d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2313d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2314d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
23160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* check if sockets are registered */
23170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2319ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
2320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2321b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        /* Mark the link state */
2322b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED;
2323b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton
23240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        while (it.hasNext()) {
23250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            RegisteredSocket registeredSocket = it.next();
2326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            switch (registeredSocket.mType) {
23280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SERVICE_SOCKET_TYPE:
2329ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Service Socket");
2330ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName);
23310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpServiceSocket serviceSocket;
23320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                serviceSocket = mManager.doCreateLlcpServiceSocket(
23340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap, registeredSocket.mServiceName,
23350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
23360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
23370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (serviceSocket != null) {
2339ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "service socket created");
23400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
23412f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
23422f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, serviceSocket);
23432f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
23440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
23456f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
23460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
23470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
23480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
23490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2350f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
2351f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // NOTE: don't remove this socket from the registered sockets list.
2352f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // If it's removed it won't be created the next time an LLCP
2353f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // connection is activated and the server won't be found.
23540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
23550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SOCKET_TYPE:
2357ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Socket");
23580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpSocket clientSocket;
23590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
23600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
23610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
23620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (clientSocket != null) {
2363ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "socket created");
23640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
23652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
23662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, clientSocket);
23672f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
23680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
23696f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
23700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
23710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
23720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
23730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2374f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2375f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
23760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
23770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_CONNECTIONLESS_SOCKET_TYPE:
2379ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket");
23800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpConnectionlessSocket connectionlessSocket;
23810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket(
23820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap);
23830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (connectionlessSocket != null) {
2384ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "connectionless socket created");
23850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
23862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
23872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
23882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
23890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
23906f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
23910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
23920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
23930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
23940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2395f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2396f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
23970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
2398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
23990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
24010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
24020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
24030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
24050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
24060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2408ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
24090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
24100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
241257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2413b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
241457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
241557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2416b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2417b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2418b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2419b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2420b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2421b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2422b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2423b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2424b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2425b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2426f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2427b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2428b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2429b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2430b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2431b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
2432b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Intent intent = buildTagIntent(tag, new NdefMessage[] { ndefMsg });
243357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
243457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
243557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               try {
243657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                   mContext.startActivity(intent);
243757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               } catch (ActivityNotFoundException e) {
243857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                   Log.w(TAG, "No activity found for mock tag");
243957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               }
244057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
244157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
244257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2443f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2444ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2445f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2446f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (nativeTag.connect()) {
24473ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                   int[] ndefinfo = new int[2];
24483ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                   if (nativeTag.checkNdef(ndefinfo)) {
24493ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                       int supportedNdefLength = ndefinfo[0];
24503ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                       int cardState = ndefinfo[1];
2451d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       boolean generateEmptyIntent = false;
2452f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       byte[] buff = nativeTag.read();
2453f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (buff != null) {
2454f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           NdefMessage[] msgNdef = new NdefMessage[1];
2455f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           try {
2456f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                               msgNdef[0] = new NdefMessage(buff);
245741368d81f3076ac903693951f1d5cdba756f33fcMartijn Coenen                               nativeTag.addNdefTechnology(msgNdef[0],
24583ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                                       supportedNdefLength, cardState);
2459b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                               Tag tag = new Tag(nativeTag.getUid(),
2460b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                       nativeTag.getTechList(),
2461b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                       nativeTag.getTechExtras(),
2462b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                       nativeTag.getHandle());
2463b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                               Intent intent = buildTagIntent(tag, msgNdef);
2464ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "NDEF tag found, starting corresponding activity");
2465ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, tag.toString());
2466b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                               try {
2467b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                                   mContext.startActivity(intent);
2468db7d865e53c4db049bab20a0bcc7cb596e450d9aSylvain Fonteneau                                   registerTagObject(nativeTag);
2469b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                               } catch (ActivityNotFoundException e) {
2470b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                                   Log.w(TAG, "No activity found, disconnecting");
247121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                                   nativeTag.disconnect();
2472b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                               }
2473f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           } catch (FormatException e) {
2474d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               // Create an intent anyway, without NDEF messages
2475d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               generateEmptyIntent = true;
2476b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2477b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       } else {
2478d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           // Create an intent anyway, without NDEF messages
2479d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           generateEmptyIntent = true;
2480d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       }
2481d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       if (generateEmptyIntent) {
2482d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           // Create an intent with an empty ndef message array
24833ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                           nativeTag.addNdefTechnology(null, supportedNdefLength, cardState);
2484b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                           Tag tag = new Tag(nativeTag.getUid(),
2485b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                   nativeTag.getTechList(),
2486b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                   nativeTag.getTechExtras(),
2487b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                                   nativeTag.getHandle());
2488b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                           Intent intent = buildTagIntent(tag, new NdefMessage[] { });
2489ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "NDEF tag found, but length 0 or invalid format, starting corresponding activity");
2490d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           try {
2491d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               mContext.startActivity(intent);
2492d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               registerTagObject(nativeTag);
2493d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           } catch (ActivityNotFoundException e) {
2494d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               Log.w(TAG, "No activity found, disconnecting");
2495d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               nativeTag.disconnect();
2496d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           }
2497b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2498f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   } else {
2499b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       Tag tag = new Tag(nativeTag.getUid(),
2500b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                               nativeTag.getTechList(),
2501b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                               nativeTag.getTechExtras(),
2502363e40d2df0d838076a68370467c0e3b9a68d4bfMartijn Coenen                               nativeTag.getHandle());
2503b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       Intent intent = buildTagIntent(tag, null);
2504ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       if (DBG) Log.d(TAG, "Non-NDEF tag found, starting corresponding activity");
2505ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       if (DBG) Log.d(TAG, tag.toString());
2506f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       try {
2507f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           mContext.startActivity(intent);
2508db7d865e53c4db049bab20a0bcc7cb596e450d9aSylvain Fonteneau                           registerTagObject(nativeTag);
2509f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } catch (ActivityNotFoundException e) {
2510f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           Log.w(TAG, "No activity found, disconnecting");
251121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                           nativeTag.disconnect();
2512f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       }
2513f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2514f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else {
2515f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   Log.w(TAG, "Failed to connect to tag");
251621545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                   nativeTag.disconnect();
2517f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2518f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2519f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2520ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2521f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
2522f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Send broadcast ordered */
2523f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TransactionIntent = new Intent();
2524f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
2525f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
2526ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
2527f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
2528f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2529f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2530f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2531f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2532f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2533f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2534f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2535f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2536ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2537f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2538f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2539f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2540f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2541f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2542ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2543eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2544eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2545eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2546eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2547eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2548b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2549b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2550f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2551ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2552f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2553b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2554eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
2555ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop.");
25564c631cd2aa3ab422d4f9f3404d6f1fabce7bdf4ddaniel_Tomas                       device.doDisconnect();
2557f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2558f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2559f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2560ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2561f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2562f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2563f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2564f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2565ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2566eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2567eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
25686f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2569ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2570f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2571b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2572f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2573f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2574f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2575eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2576eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2577eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2578cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2579ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "disconnecting from target");
2580cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   /* Restart polling loop */
2581cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   device.doDisconnect();
2582cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               } else {
2583ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "not disconnecting from initiator");
2584cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2585eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2586b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton               /* Mark the link state */
2587b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton               mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2588b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton
2589f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2590f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2591f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2592f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2593f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2594ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2595f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2596f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2597f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2598f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2599f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2600ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2601f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2602f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2603ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2604f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2605f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2606f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
260757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
260857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
260957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
261057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
261157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
261257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
261357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
261457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
261557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
261657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
261757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
261857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
261957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
262057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2621f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2622f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2623f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2624f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2625b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2626d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2627b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs) {
2628b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED);
2629b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2630b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2631b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2632b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2633d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2634d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2635b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2636b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2637b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
2638b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton
26397c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2640fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
26417c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
2642df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
2643161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2644161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
2645161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeEnableDiscovery();
2646161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
26477c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2648533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2649161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2650161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
2651161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeDisableDiscovery();
2652161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2653533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
26547c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
26557c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
26567c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
26577c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
26587c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
26590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
26600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
26610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2662eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2664ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
26650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2666f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
266765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                maybeEnableDiscovery();
2668f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
266965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
26707c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
26717c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
26727c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
26737c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2674df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(true));
267565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
26767c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
26777c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
26787c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
26797c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2680df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
2681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
268474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2685