NfcService.java revision ca1a86ecb8edce740a232c3439355e8d5b706e7a
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;
21ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushClient;
22ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushServer;
23d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.Activity;
252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
2757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport android.app.StatusBarManager;
28ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport android.app.PendingIntent.CanceledException;
29b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
37f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
38f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
39f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
40f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
41f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.INfcSecureElement;
44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
527c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
53b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
54b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
55b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
56533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
5813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
59f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
60f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
6257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
6357d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
6457d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
6557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
683ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
693ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.LinkedList;
703ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.ListIterator;
710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.Timer;
720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.TimerTask;
733ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
742f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
75ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
76fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
7757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
7857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
7913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
8013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
8113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
8213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
1003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
1013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
127d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
128fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
129f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
131bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
132bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
133bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
134bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
135bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
1420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
1450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
148e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
178a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Card Emulation Discovery mode for enableDiscovery() */
1840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
1870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_TYPE = 1;
1880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
1890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_NB_MAX = 5;  // Maximum number of socket managed
1900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_RW_MAX_VALUE = 15;  // Receive Window
191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
1980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
212b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
213b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
214b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
21657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
21757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
218b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
219c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
220c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
221b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    // Locked on mNfcAdapter
22305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    IntentFilter[] mDispatchOverrideFilters;
22405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    PendingIntent mDispatchOverrideIntent;
22505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
22674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
22774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mNbSocketCreated = 0;
23274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mSelectedSeId = 0;
2340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean mNfcSecureElementState;
235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    // Secure element
2370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private Timer mTimerOpenSmx;
2380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isClosed = false;
2390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isOpened = false;
2400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean mOpenSmxPending = false;
2410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
2420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private int mSecureElementHandle;
2430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2442f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2452f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
24765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
2482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
25005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
2510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
254533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
255ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
256ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
257d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
258d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
259d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
260d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
261d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
262d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2672f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
270d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
271d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
273b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
2740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
27574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
276ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
277ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
27857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
2820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
284d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
286533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
28752028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
288533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
289533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
290d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
292eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
29365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
29465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
2960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
3020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3173ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3183ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3194acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
320fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
322d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
333fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
336d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
338ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
3416f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
342ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                mNdefPushServer.stop();
3430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
344ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
3450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
3460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
34705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (this) {
34805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        // Clear out any old dispatch overrides
34905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
35005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
35105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
3520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
360fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
36105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
36205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                IntentFilter[] filters) {
36305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
364ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || filters == null || filters.length == 0 || intent == null) {
365ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
366ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
36705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
36805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (mDispatchOverrideFilters != null) {
36905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "Replacing active dispatch overrides");
37005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
37105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideFilters = filters;
37205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = intent;
37305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
37405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
37505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
37605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
37705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
37805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
37905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
38005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (mDispatchOverrideFilters == null && mDispatchOverrideIntent == null) {
38105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "No active foreground dispatching");
38205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
38305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideFilters = null;
38405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = null;
38505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
38605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
38705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
38805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
389ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
390ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
391ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
392ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
393ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
394ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
395ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
396ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
397ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
398ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
399ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
400ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
401ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
402ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (!mNdefPushClient.setForegroundMessage(null)) {
403ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
404ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
405ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
406ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
407ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
409d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
410bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
4170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check nb socket created */
4190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
4200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store the socket handle */
4210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
4220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
4240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket;
4250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpConnectionlessSocket(sap);
4270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
4282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
4292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
4302f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
4310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4322f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
4332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
4342f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
4350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return sockeHandle;
436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    } else {
4370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
4380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
4390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
4400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
4410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
4420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
4440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
4450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
4470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
4520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
4530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
455f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
4560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
4570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
4580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
4590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4632f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
4642f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
4652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
4660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4672f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
4682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
4692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
4700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
4710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(
4720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
4730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
4750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
4770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
4790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
4800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
4820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
4850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
486f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
4870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
490fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
493d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
494bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
5010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
5020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
5040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpServiceSocket socket;
5050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
5070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
5082f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
5092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
5102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
5112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
5122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
5132f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
5140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
5150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* socket creation error - update the socket handle counter */
5160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
5170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
5190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
5200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
5220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
5270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
5280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
5290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
5310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
5330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
5340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
5350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
5360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Service Name */
5380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketServiceName(sn)) {
5390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SERVICE_NAME_USED;
5400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
5410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check socket options */
5430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
5440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
5450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
5460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
54715151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                    NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw,
54815151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                            linearBufferLength);
5492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
5502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
5512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
5520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
5542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
5552f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
5560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
5570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
5580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, sn, miu, rw, linearBufferLength);
5590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
5610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
5630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
5650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle += 1;
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
567ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
5680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
569f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
5710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
574f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
575fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
578d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
579bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
581f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
590ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "creating llcp socket while activated");
5910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket;
5920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
5962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
5972f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
5982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
5992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
6002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
6012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
6020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
6030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
6040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
6050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
6070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
6080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6126f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                        Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
6136f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton
6140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
6150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
6170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
6210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
624ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "registering llcp socket while not activated");
625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
630f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check Socket options */
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
6330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
635bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
6372f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
6382f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
6392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
640f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6412f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
6422f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
6432f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, miu, rw, linearBufferLength);
6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
6530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
656f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
660f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
661f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
662fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int deselectSecureElement() throws RemoteException {
664d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
665f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
666f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
667f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
668f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
670f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == 0) {
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NO_SE_CONNECTED;
673f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doDeselectSecureElement(mSelectedSeId);
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = false;
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = 0;
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store preference */
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
6822f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
686f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
687fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
689d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
692bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
693fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
695d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
698f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
699fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
701d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
704f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
705fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
707d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
711fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
713d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
717fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
719d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public INfcSecureElement getNfcSecureElementInterface() {
7240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return mSecureElementService;
7260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
7270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
728fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
730d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
754f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
756f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
757f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
758f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
759fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int[] getSecureElementList() throws RemoteException {
761d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
762bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int[] list = null;
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mIsNfcEnabled == true) {
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                list = mManager.doGetSecureElementList();
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return list;
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
770fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getSelectedSecureElement() throws RemoteException {
772d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mSelectedSeId;
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
777fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
782fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void openTagConnection(Tag tag) throws RemoteException {
784b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: Remove obsolete code
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
787fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int selectSecureElement(int seId) throws RemoteException {
789d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
790f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
791f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
792f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
793f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
794f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
795f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == seId) {
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId != 0) {
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_CONNECTED;
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = seId;
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doSelectSecureElement(mSelectedSeId);
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store */
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
8102f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = true;
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
818fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
820d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
8422f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
8460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
8480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
8520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
8562f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
8600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
8620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
8660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
8702f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
8760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
8800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
8842f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
8880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
8900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
8942f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
9000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
9010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
9030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
9042f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
9050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
9070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
9080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
9100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
9110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
9130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
9142f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
9170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
9180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
9200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
9210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
9230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
9242f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
9250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
9270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
9280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
9300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
9310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
9330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
9342f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
9350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
945d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
946d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
947d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
94857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
94957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
95057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
95157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
95257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
953d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
954d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
955d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
956d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
95757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
95857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
95957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
96057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
96157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
96257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
96357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
96457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
96557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
96657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
96757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
96857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
96957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
97057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
97157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
97257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
97357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
97457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
97557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
97657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
97757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
97857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
97957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
98057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
98157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
98257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
98357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
98457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
98557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
98657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
98757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
98857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
98957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
99057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
99157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
99257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
99357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
99457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
99557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
99657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
99757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
998d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
10000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CONNECT_FLAG = 0x01;
10040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CLOSE_FLAG   = 0x02;
10050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int RECV_FLAG    = 0x04;
10060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int SEND_FLAG    = 0x08;
10070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private int concurrencyFlags;
10090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private Object sync;
10100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1011fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
1013d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1014bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
10160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1022f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
10280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
10290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Remove the socket closed from the hmap */
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        RemoveSocket(nativeHandle);
10310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Update mNbSocketCreated */
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mNbSocketCreated--;
10330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.SUCCESS;
10340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
10350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
10360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
10380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
10390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
10400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove registered socket from the list */
10420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveRegisteredSocket(nativeHandle);
10430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
10450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
10460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1049f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1054fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
1056d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1057bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1058f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1060f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1062f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1065f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1066f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1067f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1068f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
106993915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
1072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1073f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1074f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1080f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1081fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
1083d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1084bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1085f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
1086f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1087f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1088f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1089f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1090f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1091f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1092f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1093f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1094f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
109693915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
1097f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1098f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1101f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1102f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1103f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1108fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
1110d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1111bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1113f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1114f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
1123f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1126f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1127f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1128fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1130d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1131bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
11320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1134f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1138f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
11420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
11430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1148fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1150d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1151bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
11520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
11630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1168fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1170d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
11830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
11840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1192fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1194d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
12010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
12040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
12050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
12060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
12070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
12080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
12090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
12100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
12120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
12130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
12150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1216fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
12210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int receiveLength = 0;
12220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
12260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
12290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
12300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
123128f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
12320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
123328f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
12340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
12360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1237fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1239d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
12420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
12430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
12470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
12500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
12510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
12520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
12530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
12540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
12550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
12560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
12570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
12590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
12600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
12620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
12630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
12650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1266fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1268d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
12710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
12720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
12760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
12790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
12800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
12810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
128293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
12830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
12840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
12850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
12862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
12872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(clientSocket.getHandle(), clientSocket);
12882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
12892f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
12900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return clientSocket.getHandle();
12910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
12920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
12930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
12940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
12950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
12960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
12980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
12990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
13010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
13020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1303fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1305d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
13070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
13080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
13090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
13100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
13130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
13150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1316f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            boolean closed = false;
13170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
13180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
13190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
13200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
13210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
1322f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                        closed = true;
13230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
13240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
1325f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    closed = true;
1326f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                }
1327f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            }
1328f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1329f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            // If the socket is closed remove it from the socket lists
1330f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            if (closed) {
1331f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
13320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
13330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
13340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
13350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
13360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
1337f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1338f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    /* Remove registered socket from the list */
1339f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    RemoveRegisteredSocket(nativeHandle);
13400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
13410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1347fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1349d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1350bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1362f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    isSuccess = socket.doClose();
1364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    if (isSuccess) {
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Remove the socket closed from the hmap */
1366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        RemoveSocket(nativeHandle);
1367f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Update mNbSocketCreated */
1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        mNbSocketCreated--;
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove the socket closed from the hmap */
1372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveSocket(nativeHandle);
1373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove registered socket from the list */
1375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveRegisteredSocket(nativeHandle);
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Update mNbSocketCreated */
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    mNbSocketCreated--;
1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1383fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1385d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1386bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1403fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1405d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1406bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1428fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1430d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1431bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1444f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1450f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1451f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1455f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1457fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1459d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1460bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1471b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1472b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
147321545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1474b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
147765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1481fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1482ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1483d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1484bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1485f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1486f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1487f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1492f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1493f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1494b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1495b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1497ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
1498ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1499ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1500ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1501ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1502ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1503ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1504ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1505ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1507f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1508fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1509aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1510aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1511aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1512aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1513aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1514aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1515aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1516aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1517aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1518aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1519aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1520aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1521aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1522aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1523aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1524aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1525aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1526aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1527aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1528aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1529aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1530aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1531aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1532b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1533d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1534bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1535f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1538f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1539f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1540f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1541b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1543b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1544f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1548fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1551f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1552f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1553f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1554f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1559f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1560f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1561f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1564f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1565f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1566f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1567fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1568b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1569b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1570b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1571b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1572b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1573b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1574b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1575b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1576b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1577b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1578b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1579b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1580b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1581b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1582b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return tag.presenceCheck();
1583b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1584b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1585fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1586f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1587f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1588f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1589f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1590f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1591f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1593f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1596f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
15973ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
15993ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1601f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1602f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1603f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1604fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
160597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data, boolean raw)
160697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1607d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1608bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1609f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1610f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1611f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1612f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1613f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1615f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1616f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1617f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1618f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1619f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
162097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                response = tag.transceive(data, raw);
1621f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return response;
1622f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1626fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1628d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1629bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1630f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1631f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1632f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1633f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1634f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1635f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1636f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1637f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1638f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1640b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1641f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1644f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1645f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1649f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1650f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1651f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1652f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1654fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1656d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1657bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1658f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1660f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1661f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1662f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1664f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1665f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1666f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1667f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1668f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1670f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1671b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1672f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1673f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1674f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1675f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1676f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1677f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1678f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1682bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1685fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
16873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1688f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1690fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
169203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
169303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
169403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
169503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
169603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
169703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
169803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
169903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
170003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
170103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
170203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
170303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
170403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
170503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
170603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
170703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
170803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
170903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
171003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
171103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
171203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17150aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
17160aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
17170aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
17180aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
17190aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
17200aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
17210aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
17220aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
17230aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
17240aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
17250aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
17260aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
17270aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
17280aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
17290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
17300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
17310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
17320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
17330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
17340aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
17350aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
17360aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
17370aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
17380aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
17390aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1740f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1742f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1744f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1745fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1747d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1748f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1750f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
17540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1755f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1766f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1767fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1769d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1770f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1772f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1777f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1783f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1784f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1785f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1786fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1788d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1789f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1791f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
17950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1796f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
18010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
180665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1810fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1812d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1813f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
18150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1816f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
18200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1821f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
18260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
18280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
18290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1832f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1833fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1835d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1836f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1838f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
18420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1843f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
18480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
18490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
18500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
18520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1853f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1854fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1856d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1857f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
18590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1860f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
18640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1865f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
18700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1871b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
18720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
187365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                    maybeEnableDiscovery();
18740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1875f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
18760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1877f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1880fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1882d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
18850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
18860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1889f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1890f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
18950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
19000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1901f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1902fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
19030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1904d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
19090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
19100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
19140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
19150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
19160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
19170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
19180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
19190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1921fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
192297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
192397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1924d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
19290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
19300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
19340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
19350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
19360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
19370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
19380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
19390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
19400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
19410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
19420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
19430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() {
19460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int openSecureElementConnection() throws RemoteException {
19480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            Log.d(TAG, "openSecureElementConnection");
19490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int handle;
19500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
19540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check in an open is already pending
19570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mOpenSmxPending) {
19580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            handle = mSecureElement.doOpenSecureElementConnection();
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (handle == 0) {
19640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
19650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
19660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mSecureElementHandle = handle;
19670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Start timer */
19690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx = new Timer();
19700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
19730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = true;
19740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = false;
19750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = true;
19760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return handle;
19790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int closeSecureElementConnection(int nativeHandle)
19820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_NOT_INITIALIZED;
19870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
19920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
19970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElement.doDisconnect(nativeHandle)) {
20000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
20020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
20030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
20050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
20060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
20080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
20090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
20100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
20110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.SUCCESS;
20130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
20140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
20160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
20170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
20190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
20200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
20220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
20230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
20240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
20250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_DISCONNECT;
20270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int[] getSecureElementTechList(int nativeHandle)
20310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
20320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
20330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
20340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
20380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
20390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
20430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
20440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int[] techList = mSecureElement.doGetTechList(nativeHandle);
20480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
20500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
20510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
20520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
20530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return techList;
20550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] getSecureElementUid(int nativeHandle)
20580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
20590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] uid;
20600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
20620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
20630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
20670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
20680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
20720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
20730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            uid = mSecureElement.doGetUid(nativeHandle);
20770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
20790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
20800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
20810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
20820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return uid;
20840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] exchangeAPDU(int nativeHandle, byte[] data)
20870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
20880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] response;
20890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
20910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
20920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
20960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
20970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
21010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
21020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
21030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
21040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            response = mSecureElement.doTransceive(nativeHandle, data);
21060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
21080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
21090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
21100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
21110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return response;
21130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
21150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
21160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    class TimerOpenSecureElement extends TimerTask {
21180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        @Override
21200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public void run() {
21210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElementHandle != 0) {
21220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                Log.d(TAG, "Open SMX timer expired");
21230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
21240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                    mSecureElementService
21250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                            .closeSecureElementConnection(mSecureElementHandle);
21260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                } catch (RemoteException e) {
21270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                }
21280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
21290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
21310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
21330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
21340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
21350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
21360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
2137f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly            applyProperties();
2138f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check Secure Element setting */
21400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
21410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    SECURE_ELEMENT_ON_DEFAULT);
2142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNfcSecureElementState) {
21440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
21450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        SECURE_ELEMENT_ID_DEFAULT);
21460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int[] Se_list = mManager.doGetSecureElementList();
21470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (Se_list != null) {
21480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    for (int i = 0; i < Se_list.length; i++) {
21490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        if (Se_list[i] == secureElementId) {
21500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mManager.doSelectSecureElement(Se_list[i]);
21510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mSelectedSeId = Se_list[i];
21520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            break;
21530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
21540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
21550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
215865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
215965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
21600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
216165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
2164ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
216557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
21670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
2168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
2171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
2173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
217565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Enable active tag discovery if screen is on and NFC is enabled */
217665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeEnableDiscovery() {
217765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mScreenOn && mIsNfcEnabled) {
217865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.enableDiscovery(DISCOVERY_MODE_READER);
217965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
218065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
218165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
218265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Disable active tag discovery if necessary */
218365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeDisableDiscovery() {
218465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mIsNfcEnabled) {
218565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.disableDiscovery();
218665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
218765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
218865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
2189f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2190f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2191f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2192f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2193f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2194f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2195f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2196f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2197f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2198f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2199f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2200f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2201f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2202f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2203f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2204f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2205f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
22060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
22070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        int state;
2208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
22102f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
22110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
22122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
22134acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
22142f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
22154acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
22162f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
22172f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
22182f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
221957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
222157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
222357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
222557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
222657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
222757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
222857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
223057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
223157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
223257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
223357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
223457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
223557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
223657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
223757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
223857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
223957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
224057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
224157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
224257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
224357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
224457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
224557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
224657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
224757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
224857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
224957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
225057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
225157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
225257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
225357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
225457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
225557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
225657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
225757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
225857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
225957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
226057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
226157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
226257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
226357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
226457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
226557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
226657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
226757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
22680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
22722f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
227374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
227474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mRegisteredSocketList.clear();
2280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mNbSocketCreated = 0;
2284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSelectedSeId = 0;
2286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2300b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2301b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2302b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
23032f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2304b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object socket = null;
2309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        socket = mSocketMap.get(key);
2311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return socket;
2313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketSap(int sap) {
2320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sap == registeredSocket.mSap) {
2327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* SAP already used */
2328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
2335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) {
2337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return false;
2338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketServiceName(String sn) {
2343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sn.equals(registeredSocket.mServiceName)) {
2351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Service Name already used */
2352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveRegisteredSocket(int nativeHandle) {
2359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* check if sockets are registered */
2360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2362f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (registeredSocket.mHandle == nativeHandle) {
2365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* remove the registered socket from the list */
2366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                it.remove();
2367ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "socket removed");
2368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    /*
2373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * RegisteredSocket class to store the creation request of socket until the
2374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * LLCP link in not activated
2375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     */
2376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private class RegisteredSocket {
2377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mType;
2378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mHandle;
2380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mSap;
2382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mMiu;
2384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mRw;
2386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private String mServiceName;
2388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mlinearBufferLength;
2390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
2392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                int linearBufferLength) {
2393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mServiceName = sn;
2397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
2403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap) {
2412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2418d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2419d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2420d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2421d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
24221be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
24231be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
24241be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
24251be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2426d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2427d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2428d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2429d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2430d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2431d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2432d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2433d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2434d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2435d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2436d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2437d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
24381be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
24391be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
24401be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
24411be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2442d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2443d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2444d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2445d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2446d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2447d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2448d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
24490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
24500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* check if sockets are registered */
24510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2453ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
2454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2455b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        /* Mark the link state */
2456b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED;
2457b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton
24580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        while (it.hasNext()) {
24590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            RegisteredSocket registeredSocket = it.next();
2460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
24610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            switch (registeredSocket.mType) {
24620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SERVICE_SOCKET_TYPE:
2463ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Service Socket");
2464ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName);
24650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpServiceSocket serviceSocket;
24660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
24670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                serviceSocket = mManager.doCreateLlcpServiceSocket(
24680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap, registeredSocket.mServiceName,
24690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
24700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
24710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
24720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (serviceSocket != null) {
2473ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "service socket created");
24740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
24752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
24762f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, serviceSocket);
24772f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
24780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
24796f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
24800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
24810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
24820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
24830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2484f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
2485f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // NOTE: don't remove this socket from the registered sockets list.
2486f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // If it's removed it won't be created the next time an LLCP
2487f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // connection is activated and the server won't be found.
24880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
24890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
24900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SOCKET_TYPE:
2491ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Socket");
24920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpSocket clientSocket;
24930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
24940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
24950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
24960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (clientSocket != null) {
2497ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "socket created");
24980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
24992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
25002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, clientSocket);
25012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
25020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
25036f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
25040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
25050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
25060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
25070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2508f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2509f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
25100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
25110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
25120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_CONNECTIONLESS_SOCKET_TYPE:
2513ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket");
25140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpConnectionlessSocket connectionlessSocket;
25150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket(
25160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap);
25170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (connectionlessSocket != null) {
2518ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "connectionless socket created");
25190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
25202f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
25212f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
25222f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
25230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
25246f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
25250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
25260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
25270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
25280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2529f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2530f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
25310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
2532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
25330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
25350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
25360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
25370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2538f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
25390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
25400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2542ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
25430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
25440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
254657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2547b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
254857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
254957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2550b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2551b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2552b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2553b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2554b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2555b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2556b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2557b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2558232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2559232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
2560232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            // Try to find NDEF on any of the technologies.
2561232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] technologies = nativeTag.getTechList();
2562232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] handles = nativeTag.getHandleList();
2563232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int techIndex = 0;
2564232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int lastHandleScanned = 0;
2565232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            boolean ndefFoundAndConnected = false;
2566232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            NdefMessage[] ndefMsgs = null;
2567eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen            boolean foundFormattable = false;
2568232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2569232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
2570232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                if (handles[techIndex] != lastHandleScanned) {
2571232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    // We haven't seen this handle yet, connect and checkndef
2572232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    if (nativeTag.connect(technologies[techIndex])) {
2573eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        // Check if this type is NDEF formatable
2574eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        if (!foundFormattable && (nativeTag.isNdefFormatable())) {
2575eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                            foundFormattable = true;
2576eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                            nativeTag.addNdefFormatableTechnology(
2577eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                                    nativeTag.getConnectedHandle(),
2578eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                                    nativeTag.getConnectedTechnology());
2579eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        } // else not formatable
2580232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        int[] ndefinfo = new int[2];
2581232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        if (nativeTag.checkNdef(ndefinfo)) {
2582232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            ndefFoundAndConnected = true;
2583232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            boolean generateEmptyNdef = false;
2584232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2585232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int supportedNdefLength = ndefinfo[0];
2586232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int cardState = ndefinfo[1];
2587232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            byte[] buff = nativeTag.read();
2588232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            if (buff != null) {
2589232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                ndefMsgs = new NdefMessage[1];
2590232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                try {
2591232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    ndefMsgs[0] = new NdefMessage(buff);
2592232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.addNdefTechnology(ndefMsgs[0],
2593ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                            nativeTag.getConnectedHandle(),
25940a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                            nativeTag.getConnectedLibNfcType(),
2595f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                            nativeTag.getConnectedTechnology(),
2596232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                            supportedNdefLength, cardState);
2597232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.reconnect();
2598232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                } catch (FormatException e) {
2599232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   // Create an intent anyway, without NDEF messages
2600232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   generateEmptyNdef = true;
2601232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                }
2602232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            } else {
2603232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                generateEmptyNdef = true;
2604232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
2605232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2606232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           if (generateEmptyNdef) {
2607232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               ndefMsgs = new NdefMessage[] { };
2608ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                               nativeTag.addNdefTechnology(null,
2609ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       nativeTag.getConnectedHandle(),
26100a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                       nativeTag.getConnectedLibNfcType(),
2611f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                       nativeTag.getConnectedTechnology(),
2612ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       supportedNdefLength, cardState);
2613232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               nativeTag.reconnect();
2614232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           }
2615232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        } // else, no NDEF on this tech, continue loop
2616232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    } else {
2617232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // Connect failed, tag maybe lost. Try next handle
2618232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // anyway.
2619232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    }
2620232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2621232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                lastHandleScanned = handles[techIndex];
2622232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                techIndex++;
2623232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            }
2624232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2625232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            return ndefMsgs;
2626232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
2627232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2628b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2629b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2630f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2631b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2632b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2633b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2634b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2635b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
263657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
263757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
26383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
263957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
264057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
264157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2642f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2643ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2644f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2645232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2646232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2647232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
264898eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2649232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2650232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2651232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2652232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
265398eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
26543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2655232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2656232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2657232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2658f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2659f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2660f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
26613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2662f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2663ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2664f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
2665f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Send broadcast ordered */
2666f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TransactionIntent = new Intent();
2667f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
2668f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
2669ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
2670f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
2671f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2672f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2673f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2674f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2675f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2676f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2677f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2678f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2679ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2680f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2681f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2682f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2683f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2684f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2685ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2686eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2687eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2688eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2689eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2690eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2691b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2692b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2693f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2694ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2695f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2696b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2697eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
2698ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop.");
26994c631cd2aa3ab422d4f9f3404d6f1fabce7bdf4ddaniel_Tomas                       device.doDisconnect();
2700f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2701f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2702f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2703ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2704f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2705f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2706f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2707f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2708ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2709eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2710eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
27116f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2712ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2713f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2714b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2715f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2716f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2717f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2718eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2719eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
27201b147b40e00cb6224d07f9185b19e6262c387ed6Sylvain Fonteneau               /* Mark the link state */
27211b147b40e00cb6224d07f9185b19e6262c387ed6Sylvain Fonteneau               mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
27221b147b40e00cb6224d07f9185b19e6262c387ed6Sylvain Fonteneau
2723eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2724cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2725ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "disconnecting from target");
2726cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   /* Restart polling loop */
2727cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   device.doDisconnect();
2728cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               } else {
2729ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "not disconnecting from initiator");
2730cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2731eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2732f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2733f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2734f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2735f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2736f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2737ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2738f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2739f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2740f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2741f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2742f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2743ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2744f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2745f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2746ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2747f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2748f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2749f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
275057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
275157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
275257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
275357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
275457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
275557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
275657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
275757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
275857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
275957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
276057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
276157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
276257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
276357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2764c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2765c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2766c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
2767c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               eventFieldOnIntent.setAction(NfcAdapter.ACTION_RF_FIELD_ON_DETECTED);
2768c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
2769c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               mContext.sendBroadcast(eventFieldOnIntent, NFC_PERM);
2770c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2771c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2772c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2773c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2774c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2775c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
2776c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               eventFieldOffIntent.setAction(NfcAdapter.ACTION_RF_FIELD_OFF_DETECTED);
2777c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
2778c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               mContext.sendBroadcast(eventFieldOffIntent, NFC_PERM);
2779c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2780c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2781c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2782f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2783f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2784f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2785f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2786b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2787d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
27883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
27893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2790b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2791b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2792b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2793b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2794d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2795d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
27963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
27983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
27993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle());
28003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (dispatchTag(tag, msgs)) {
28013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                registerTagObject(nativeTag);
28023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            } else {
28033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
28043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
28063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
28083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
28093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
28103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
28113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
28133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
28143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
28153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
28163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
28173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
28193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
28203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
28223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
28233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
28253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
28263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
28273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
28283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
28293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
28303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
28313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
28323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
28333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
28343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
28353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
28363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
28383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
28393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
28403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            switch (tnf) {
28413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_MIME_MEDIA: {
28423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent.setType(new String(type, Charsets.US_ASCII));
28433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return true;
28443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
28453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_ABSOLUTE_URI: {
28463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
28473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return true;
28483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
28493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_WELL_KNOWN: {
28503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
28513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        intent.setType("text/plain");
28523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
28533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
28543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        // Parse the smart poster looking for the URI
28553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        try {
28563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            NdefMessage msg = new NdefMessage(record.getPayload());
28573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            for (NdefRecord subRecord : msg.getRecords()) {
28583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                if (subRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN
28593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                        && Arrays.equals(subRecord.getType(), NdefRecord.RTD_URI)) {
28603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                    intent.setData(parseWellKnownUriRecord(subRecord));
28613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                    return true;
28623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
28633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
28643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        } catch (FormatException e) {
28653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            return false;
28663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
28673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
28683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        intent.setData(parseWellKnownUriRecord(record));
28693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
28703fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
28713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return false;
28723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
28733fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return false;
28753fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
28763fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri buildTechListUri(Tag tag) {
28783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int[] techList = tag.getTechnologyList();
28793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Arrays.sort(techList);
28803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Uri.Builder builder = new Uri.Builder();
28813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            builder.scheme("vnd.android.nfc").authority("tag");
28823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (int tech : techList) {
28833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                builder.appendPath(Integer.toString(tech));
28843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            builder.appendPath("");
28863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return builder.build();
28873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
28883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
28903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
28913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
28923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
28933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
28943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
289605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            IntentFilter[] overrideFilters;
289705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            PendingIntent overrideIntent;
289805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (mNfcAdapter) {
289905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideFilters = mDispatchOverrideFilters;
290005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideIntent = mDispatchOverrideIntent;
290105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
290205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
290305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // First look for dispatch overrides
290405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideFilters != null && overrideIntent != null) {
290505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
290605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
290705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters)) {
290805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        if (DBG) Log.d(TAG, "Dispatched to override");
290905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
291005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
291105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch override registered, but no filters matched");
291205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (CanceledException e) {
291305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
291405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (mNfcAdapter) {
291505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
291605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
291705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
291805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
291905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
292005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
292105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // Try a standard dispatch
292205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            try {
292305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                return dispatchTagInternal(tag, msgs, null, null);
292405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } catch (CanceledException e) {
292505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                Log.e(TAG, "CanceledException unexpected here", e);
292605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                return false;
292705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
292805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
292905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
293005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        // Dispatch to either an override pending intent or a standard startActivity()
293105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
293205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                PendingIntent overrideIntent, IntentFilter[] overrideFilters)
293305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                throws CanceledException{
29343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
29353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
29363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
29373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
29383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
29393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
29403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
29413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
29423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
29433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    setTypeOrDataFromNdef(intent, record);
29443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
294505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
29463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        // If an activity is found then skip further dispatching
29473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
294805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    } else {
29493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
29503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
29513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
29523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
29533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
29543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
29553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
29563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent.setData(buildTechListUri(tag));
295705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
29583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
295905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
29603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
29613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
29623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
29633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
29643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
296505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters)) {
29663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
296705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
29683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
29693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
29703fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
29713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
297205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
297305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
297405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                IntentFilter[] overrideFilters) throws CanceledException {
297505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideIntent != null) {
297605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                for (IntentFilter filter : overrideFilters) {
297705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
297805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        Log.i(TAG, "Dispatching to override intent " + overrideIntent);
297905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        overrideIntent.send(mContext, Activity.RESULT_OK, intent);
298005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
298105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
298205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
298305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                return false;
298405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
298505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
298605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    mContext.startActivity(intent);
298705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return true;
298805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (ActivityNotFoundException e) {
298905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return false;
299005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
299105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
299205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
2993b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2994b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2995b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
2996b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton
29977c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2998fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
29997c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
3000df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
3001161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
3002161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
3003161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeEnableDiscovery();
3004161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
30057c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
3006533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
3007161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
3008161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
3009161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeDisableDiscovery();
3010161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
3011533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
30127c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
30137c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
30147c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
30157c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
30167c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
30170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
30180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
30190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
3020eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
3021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
3022ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
30230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
302565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                maybeEnableDiscovery();
3026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
302765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
30287c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
30297c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
30307c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
30317c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
3032df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(true));
303365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
30347c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
30357c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
30367c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
30377c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
3038df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
3039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
3041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
304274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
3043