NfcService.java revision 3fb30ae5bf51d9ffe6271a345d55905dade8040d
1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License.
6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at
7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software
11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and
14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License.
15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellypackage com.android.nfc;
18f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpServiceSocket;
20d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpSocket;
2157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport com.android.nfc.mytag.MyTagClient;
2257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport com.android.nfc.mytag.MyTagServer;
23d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport android.app.StatusBarManager;
26b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
2713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
2813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
2913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
33f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
34f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
35f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
36f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
37f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.INfcSecureElement;
40f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
41f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
42f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
487c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
49b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
50b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
51b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
52533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
5413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
5857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
5957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
6057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
6157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
643ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
653ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.LinkedList;
663ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.ListIterator;
670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.Timer;
680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.TimerTask;
693ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
702f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
71ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
72fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
7357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
7457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
7513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
7613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
7713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
7813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
123d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
124fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
126f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
127bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
128bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
129bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
130bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
131bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
1380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
1410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
144e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
174a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Card Emulation Discovery mode for enableDiscovery() */
1800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
1830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_TYPE = 1;
1840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
1850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_SOCKET_NB_MAX = 5;  // Maximum number of socket managed
1860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_RW_MAX_VALUE = 15;  // Receive Window
187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
1940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
1980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
207b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
208b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
209b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
210b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
21257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
21357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
214b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
21674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
21774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mNbSocketCreated = 0;
22274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mSelectedSeId = 0;
2240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean mNfcSecureElementState;
225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    // Secure element
2270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private Timer mTimerOpenSmx;
2280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isClosed = false;
2290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isOpened = false;
2300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean mOpenSmxPending = false;
2310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
2320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private int mSecureElementHandle;
2330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2342f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2352f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2362f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
23765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
2382f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
2400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private Context mContext;
2410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
244533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
24557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private MyTagServer mMyTagServer;
24657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private MyTagClient mMyTagClient;
247d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
248d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
249d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
250d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
251d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
252d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2562f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2572f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2582f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
260d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
261d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
263b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
2640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
26574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
26657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton        mMyTagServer = new MyTagServer();
26757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton        mMyTagClient = new MyTagClient(this);
26857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
274d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
276533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
27752028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
278533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
279533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
280d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
282eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
28365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
28465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
2850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
2860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
2900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
2910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
2920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
2960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
2970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3022f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3073ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3083ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3094acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
310fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
323fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
326d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
328ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
3316f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
33257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mMyTagServer.stop();
3330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
334ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
3350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
3360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
3410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
345fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
347d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
348bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
3550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check nb socket created */
3570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
3580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store the socket handle */
3590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
3600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
3620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket;
3630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpConnectionlessSocket(sap);
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
3662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
3672f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
3682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
3690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3702f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
3712f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
3722f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
3730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return sockeHandle;
374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    } else {
3750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
3760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
3780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
3790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
3800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
3820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
3830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
3850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
3860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
3870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
3880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
3890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
3900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
3910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
3940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
3950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
3960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
4022f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
4032f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
4040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4052f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
4062f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
4072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
4080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
4090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(
4100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
4110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
4130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
4150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
4170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
4180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
4200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
4230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
4250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
428fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
431d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
432bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
4390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
4400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
4420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpServiceSocket socket;
4430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
4450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
4462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
4472f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
4482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
4492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
4502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
4512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
4520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
4530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* socket creation error - update the socket handle counter */
4540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
4550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
4570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
4580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
4600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
4650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
4660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
4670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
4690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
4710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
4720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
4730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Service Name */
4760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketServiceName(sn)) {
4770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SERVICE_NAME_USED;
4780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check socket options */
4810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
4820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
4830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
4840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
48515151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                    NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw,
48615151d5453f9b9b3680cb254ccea42458cc51f33Jeff Hamilton                            linearBufferLength);
4872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
4882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
4892f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
4900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
4922f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
4932f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
4940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
4950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
4960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, sn, miu, rw, linearBufferLength);
4970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
5010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
5030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle += 1;
5040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
505ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
5060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
507f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
5090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
510f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
511f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
512f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
513fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
516d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
517bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
521f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
522f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
5240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int sockeHandle = mGeneratedSocketHandle;
5260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
528ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "creating llcp socket while activated");
5290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket;
5300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
5320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (socket != null) {
5342f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(NfcService.this) {
5352f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Update the number of socket created */
5362f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
5372f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            /* Add the socket into the socket map */
5382f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(sockeHandle, socket);
5392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
5400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
5410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /*
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * socket creation error - update the socket handle
5430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         * generation
5440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                         */
5450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mGeneratedSocketHandle -= 1;
5460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Get Error Status */
5480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        int errorStatus = mManager.doGetLastError();
5490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5506f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                        Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
5516f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton
5520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        switch (errorStatus) {
5530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            default:
5580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                                return ErrorCodes.ERROR_SOCKET_CREATION;
5590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
5600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
561f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
562ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "registering llcp socket while not activated");
563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check SAP is not already used */
5650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketSap(sap)) {
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SAP_USED;
5670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Check Socket options */
5700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
5710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_SOCKET_OPTIONS;
5720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
573bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
5752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
5762f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Add the socket into the socket map */
5772f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(sockeHandle, socket);
578f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        /* Update the number of socket created */
5802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mNbSocketCreated++;
5812f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
5820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Create new registered socket */
5830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
5840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            sockeHandle, sap, miu, rw, linearBufferLength);
5850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Put this socket into a list of registered socket */
5870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mRegisteredSocketList.add(registeredSocket);
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
5890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* update socket handle generation */
5910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mGeneratedSocketHandle++;
5920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return sockeHandle;
594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* No socket available */
5960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
597f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
599f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
600fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int deselectSecureElement() throws RemoteException {
602d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
603f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
605f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
606f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
607f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
608f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == 0) {
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NO_SE_CONNECTED;
611f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doDeselectSecureElement(mSelectedSeId);
6140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = false;
6150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = 0;
6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store preference */
6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
6202f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
6210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
625fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
627d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
630bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
631fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
633d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
636f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
637fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
639d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
643fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
645d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
649fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
651d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
655fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
657d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public INfcSecureElement getNfcSecureElementInterface() {
6620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return mSecureElementService;
6640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
666fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
668d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
6820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
6840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
6860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
6870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
692f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
694f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
695f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
697fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int[] getSecureElementList() throws RemoteException {
699d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
700bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int[] list = null;
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mIsNfcEnabled == true) {
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                list = mManager.doGetSecureElementList();
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return list;
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
708fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getSelectedSecureElement() throws RemoteException {
710d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mSelectedSeId;
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
715fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
720fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void openTagConnection(Tag tag) throws RemoteException {
722b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: Remove obsolete code
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
725fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int selectSecureElement(int seId) throws RemoteException {
727d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
728f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
729f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
730f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
732f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
733f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == seId) {
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId != 0) {
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_CONNECTED;
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = seId;
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doSelectSecureElement(mSelectedSeId);
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store */
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
7482f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = true;
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
756fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
758d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
7802f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
7840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
7942f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
8082f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
8222f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
8322f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
8422f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
8460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
8480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
8522f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
8560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
8580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
8622f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
8660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
8680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
8722f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
8760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
877f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
882f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
883d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
884d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
885d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
88657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
88757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
88857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
88957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
89057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
891d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
892d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
893d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
894d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
89557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
89657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
89757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
89857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
89957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
90057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
90157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
90257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
90357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
90457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
90557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
90657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
90757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
90857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
90957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
91057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
91157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
91257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
91357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
91457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
91557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
91657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
91757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
91857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
91957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
92057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
92157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
92257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
92357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
92457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
92557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
92657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
92757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
92857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
92957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
93057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
93157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
93257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
93357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
93457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
93557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
936d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
9400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CONNECT_FLAG = 0x01;
9420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int CLOSE_FLAG   = 0x02;
9430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int RECV_FLAG    = 0x04;
9440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private final int SEND_FLAG    = 0x08;
9450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private int concurrencyFlags;
9470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        private Object sync;
9480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
949fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
951d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
952bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
9650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
9660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
9670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Remove the socket closed from the hmap */
9680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        RemoveSocket(nativeHandle);
9690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Update mNbSocketCreated */
9700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        mNbSocketCreated--;
9710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.SUCCESS;
9720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
9730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
9740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
9760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
9770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
9780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove registered socket from the list */
9800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveRegisteredSocket(nativeHandle);
9810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
9830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
9840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
992fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
994d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
995bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
100793915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
10080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
10090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
10160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1019fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
1021d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1022bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
103493915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1042f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
10430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1045f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1046fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
1048d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1049bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1054f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1055f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1056f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
10580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1065f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1066fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1068d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1069bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1071f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1073f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
1079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1083f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1084f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1085f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1086fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1088d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1089bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1091f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1092f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1093f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1094f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1096f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1097f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
10990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
11010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
11030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1106fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1108d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
11210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
11220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1130fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1132d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
11450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
11460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
11510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1154fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1156d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int receiveLength = 0;
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
116928f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
11700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
117128f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
11720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1175fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1177d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
11880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpSocket) findSocket(nativeHandle);
11890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
11910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
11920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
11930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
11980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
12000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
12010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
12030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1204fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1206d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
12090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
12100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
12140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
12170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
12180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
12190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
122093915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
12210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
12220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
12230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
12242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
12252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mSocketMap.put(clientSocket.getHandle(), clientSocket);
12262f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                            mNbSocketCreated++;
12272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
12280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return clientSocket.getHandle();
12290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
12300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
12310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
12320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
12330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
12340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
12360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
12370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
12400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1241fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1243d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
12460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
12470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
12490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
12500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
12510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1254f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            boolean closed = false;
12550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
12560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
12570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
12580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    isSuccess = socket.doClose();
12590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (isSuccess) {
1260f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                        closed = true;
12610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
12620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
1263f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    closed = true;
1264f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                }
1265f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            }
1266f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1267f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            // If the socket is closed remove it from the socket lists
1268f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton            if (closed) {
1269f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
12700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
12710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
12720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
12730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Update mNbSocketCreated */
12740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mNbSocketCreated--;
1275f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
1276f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    /* Remove registered socket from the list */
1277f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                    RemoveRegisteredSocket(nativeHandle);
12780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1285fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1287d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1288bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) {
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    isSuccess = socket.doClose();
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    if (isSuccess) {
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Remove the socket closed from the hmap */
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        RemoveSocket(nativeHandle);
1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        /* Update mNbSocketCreated */
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                        mNbSocketCreated--;
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    }
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove the socket closed from the hmap */
1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveSocket(nativeHandle);
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Remove registered socket from the list */
1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    RemoveRegisteredSocket(nativeHandle);
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    /* Update mNbSocketCreated */
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    mNbSocketCreated--;
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1321fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1323d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1324bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1341fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1343d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1344bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1362f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1366fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1367f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1368d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1369bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1395fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1397d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1398bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1409b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1410b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
141121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1412b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
141565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
1416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1419fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int connect(int nativeHandle) throws RemoteException {
1421d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1422bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1430f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1432b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1433b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1435b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: register the tag as being locked rather than really connect
1436b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return ErrorCodes.SUCCESS;
1437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1439fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1440aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1441aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1442aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1443aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1444aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1445aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1446aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1447aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1448aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1449aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1450aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1451aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1452aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1453aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1454aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1455aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1456aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1457aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1458aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1459aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1460aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1461aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1462aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1463b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1464d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1465bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1472b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1474b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1477f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1479fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1485f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1486f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1487f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1492f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1493f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1498fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1499b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1500b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1501b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1502b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1503b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1504b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1505b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1506b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1507b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1508b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1509b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1510b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1511b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1512b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1513b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return tag.presenceCheck();
1514b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1515b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1516fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1521f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1522f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1526f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
15283ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
15303ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1535fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
153697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data, boolean raw)
153797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1538d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1539bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1540f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1544f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
155197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                response = tag.transceive(data, raw);
1552f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return response;
1553f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1554f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1557fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1559d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1560bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1561f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1564f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1565f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1566f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1567f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1569f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1570f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1571b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1574f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1575f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1576f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1577f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1578f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1579f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1581f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1585fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1587d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1588bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1589f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1590f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1591f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1593f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1596f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1597f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1599f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1601f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1602b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1603f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1605f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1606f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1607f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1608f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1609f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1610f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1611fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1612f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
16133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1615f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1616fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
16183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1619f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1621fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
16233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16260aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
16270aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
16280aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
16310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
16330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
16340aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
16350aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16360aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16370aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
16380aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
16390aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
16400aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
16410aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16420aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16430aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
16440aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
16450aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16460aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
16470aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
16480aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16490aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
16500aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1651f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1656fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1658d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1661f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1666f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1677f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1678fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1680d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1688f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1694f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1695f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1697fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1699d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1700f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1707f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
171765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1720f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1721fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1723d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1724f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1732f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
17370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
17390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1741f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1743f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1744fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1746d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1747f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
17530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1754f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
17590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
17600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1764f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1765fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1767d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1768f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1771f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1776f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
17810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1782b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
17830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
178465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                    maybeEnableDiscovery();
17850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1786f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
17870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1788f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1790f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1791fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1793d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1794f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
17970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1800f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1801f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
18060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1812f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1813fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1815d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1816f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1822f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1823f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
18280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
18300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1832fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
183397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
183497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                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 null;
1842f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1843f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
18480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
18540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1855f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() {
18570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int openSecureElementConnection() throws RemoteException {
18590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            Log.d(TAG, "openSecureElementConnection");
18600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int handle;
18610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check in an open is already pending
18680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mOpenSmxPending) {
18690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            handle = mSecureElement.doOpenSecureElementConnection();
18730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (handle == 0) {
18750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
18770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mSecureElementHandle = handle;
18780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Start timer */
18800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx = new Timer();
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
18820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = true;
18850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = false;
18860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = true;
18870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return handle;
18900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int closeSecureElementConnection(int nativeHandle)
18930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
18940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_NOT_INITIALIZED;
18980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
19030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
19080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElement.doDisconnect(nativeHandle)) {
19110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
19130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
19140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
19160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
19170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
19190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
19200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
19210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
19220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.SUCCESS;
19240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
19250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
19270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
19280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
19300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
19310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
19330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
19340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
19350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
19360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_DISCONNECT;
19380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int[] getSecureElementTechList(int nativeHandle)
19420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int[] techList = mSecureElement.doGetTechList(nativeHandle);
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return techList;
19660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] getSecureElementUid(int nativeHandle)
19690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] uid;
19710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            uid = mSecureElement.doGetUid(nativeHandle);
19880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return uid;
19950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] exchangeAPDU(int nativeHandle, byte[] data)
19980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] response;
20000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
20020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
20030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
20070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
20080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
20120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
20130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
20140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            response = mSecureElement.doTransceive(nativeHandle, data);
20170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
20190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
20200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
20210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
20220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return response;
20240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
20270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    class TimerOpenSecureElement extends TimerTask {
20290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        @Override
20310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public void run() {
20320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElementHandle != 0) {
20330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                Log.d(TAG, "Open SMX timer expired");
20340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
20350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                    mSecureElementService
20360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                            .closeSecureElementConnection(mSecureElementHandle);
20370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                } catch (RemoteException e) {
20380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                }
20390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
20440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
20460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
20470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
2048f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly            applyProperties();
2049f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
20500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check Secure Element setting */
20510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
20520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    SECURE_ELEMENT_ON_DEFAULT);
2053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNfcSecureElementState) {
20550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
20560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        SECURE_ELEMENT_ID_DEFAULT);
20570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int[] Se_list = mManager.doGetSecureElementList();
20580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (Se_list != null) {
20590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    for (int i = 0; i < Se_list.length; i++) {
20600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        if (Se_list[i] == secureElementId) {
20610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mManager.doSelectSecureElement(Se_list[i]);
20620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mSelectedSeId = Se_list[i];
20630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            break;
20640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
20650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
20660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2067f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2068f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
206965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
207065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
207265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
207357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
207457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
207557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mMyTagServer.start();
207657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
20780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
2079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2080f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
2082f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
2084f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2085f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
208665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Enable active tag discovery if screen is on and NFC is enabled */
208765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeEnableDiscovery() {
208865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mScreenOn && mIsNfcEnabled) {
208965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.enableDiscovery(DISCOVERY_MODE_READER);
209065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
209165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
209265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
209365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Disable active tag discovery if necessary */
209465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeDisableDiscovery() {
209565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mIsNfcEnabled) {
209665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.disableDiscovery();
209765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
209865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
209965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
2100f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2101f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2102f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2103f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2104f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2105f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2106f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2107f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2108f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2109f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2110f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2111f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2112f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2113f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2114f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2115f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2116f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
21180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        int state;
2119f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
21212f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
21220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
21232f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
21244acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
21252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
21264acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
21272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
21282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
21292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
213057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
213157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
213257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
213357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
213457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
213557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
213657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
213757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
213857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
213957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
214057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
214157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
214257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
214357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
214457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
214557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
214657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
214757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
214857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
214957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
215057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
215157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
215357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
215457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
215557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
215657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
215757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
215857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
215957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
216057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
216157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
216457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
216557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
216657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
216757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
216857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
216957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
217057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
217157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
217257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
217357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
217457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
217557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
217657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
217757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
217857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
21790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
21832f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
218474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
218574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mRegisteredSocketList.clear();
2191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mNbSocketCreated = 0;
2195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSelectedSeId = 0;
2197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2212b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2213b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22142f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22182f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object socket = null;
2220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        socket = mSocketMap.get(key);
2222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return socket;
2224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketSap(int sap) {
2231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sap == registeredSocket.mSap) {
2238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* SAP already used */
2239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
2246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) {
2248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return false;
2249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private boolean CheckSocketServiceName(String sn) {
2254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* List of sockets registered */
2256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (sn.equals(registeredSocket.mServiceName)) {
2262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Service Name already used */
2263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return false;
2264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return true;
2267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveRegisteredSocket(int nativeHandle) {
2270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        /* check if sockets are registered */
2271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        while (it.hasNext()) {
2274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            RegisteredSocket registeredSocket = it.next();
2275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (registeredSocket.mHandle == nativeHandle) {
2276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* remove the registered socket from the list */
2277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                it.remove();
2278ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "socket removed");
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    /*
2284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * RegisteredSocket class to store the creation request of socket until the
2285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     * LLCP link in not activated
2286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly     */
2287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private class RegisteredSocket {
2288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mType;
2289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mHandle;
2291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private final int mSap;
2293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mMiu;
2295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mRw;
2297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private String mServiceName;
2299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        private int mlinearBufferLength;
2301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
2303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                int linearBufferLength) {
2304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mServiceName = sn;
2308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
2314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mRw = rw;
2318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mMiu = miu;
2319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mlinearBufferLength = linearBufferLength;
2320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        RegisteredSocket(int type, int handle, int sap) {
2323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mType = type;
2324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mHandle = handle;
2325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            mSap = sap;
2326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2329d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2330d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2331d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2332d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
23331be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23341be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23351be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23361be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2337d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2338d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2339d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2340d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2341d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2342d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2343d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2344d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2345d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2346d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2347d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2348d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
23491be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23501be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23511be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23521be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2353d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2354d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2355d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2356d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2357d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2358d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2359d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
23610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* check if sockets are registered */
23620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
2363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2364ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
2365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2366b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        /* Mark the link state */
2367b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton        mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED;
2368b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton
23690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        while (it.hasNext()) {
23700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            RegisteredSocket registeredSocket = it.next();
2371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            switch (registeredSocket.mType) {
23730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SERVICE_SOCKET_TYPE:
2374ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Service Socket");
2375ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName);
23760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpServiceSocket serviceSocket;
23770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                serviceSocket = mManager.doCreateLlcpServiceSocket(
23790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap, registeredSocket.mServiceName,
23800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
23810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
23820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
23830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (serviceSocket != null) {
2384ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "service socket created");
23850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
23862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
23872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, serviceSocket);
23882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
23890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
23906f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
23910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
23920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
23930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
23940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2395f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton
2396f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // NOTE: don't remove this socket from the registered sockets list.
2397f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // If it's removed it won't be created the next time an LLCP
2398f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // connection is activated and the server won't be found.
23990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
24000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
24010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_SOCKET_TYPE:
2402ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Socket");
24030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpSocket clientSocket;
24040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
24050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mMiu, registeredSocket.mRw,
24060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mlinearBufferLength);
24070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (clientSocket != null) {
2408ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "socket created");
24090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
24102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
24112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, clientSocket);
24122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
24130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
24146f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
24150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
24160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
24170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
24180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2419f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2420f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
24210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
24220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
24230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            case LLCP_CONNECTIONLESS_SOCKET_TYPE:
2424ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket");
24250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NativeLlcpConnectionlessSocket connectionlessSocket;
24260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket(
24270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        registeredSocket.mSap);
24280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (connectionlessSocket != null) {
2429ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                    if (DBG) Log.d(TAG, "connectionless socket created");
24300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Add the socket into the socket map */
24312f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    synchronized(NfcService.this) {
24322f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
24332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                    }
24340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
24356f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                    Log.d(TAG, "FAILED to create service socket");
24360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* socket creation error - update the socket
24370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                     * handle counter */
24380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mGeneratedSocketHandle -= 1;
24390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2440f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                // This socket has been created, remove it from the registered sockets list.
2441f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                it.remove();
24420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                break;
2443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
24440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
24460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
24470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
24480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
24500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
24510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2453ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
24540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
24550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
245757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2458b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
245957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
246057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2461b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2462b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2463b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2464b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2465b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2466b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2467b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2468b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2469b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2470b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2471f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2472b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2473b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2474b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2475b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2476b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
247757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
247857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
24793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
248057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
248157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
248257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2483f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2484ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2485f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2486f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (nativeTag.connect()) {
24873ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                   int[] ndefinfo = new int[2];
24883ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                   if (nativeTag.checkNdef(ndefinfo)) {
24893ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                       int supportedNdefLength = ndefinfo[0];
24903ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                       int cardState = ndefinfo[1];
2491d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       boolean generateEmptyIntent = false;
2492f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       byte[] buff = nativeTag.read();
2493f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (buff != null) {
2494f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           NdefMessage[] msgNdef = new NdefMessage[1];
2495f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           try {
2496f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                               msgNdef[0] = new NdefMessage(buff);
249741368d81f3076ac903693951f1d5cdba756f33fcMartijn Coenen                               nativeTag.addNdefTechnology(msgNdef[0],
24983ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                                       supportedNdefLength, cardState);
24993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                               dispatchNativeTag(nativeTag, msgNdef);
2500f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           } catch (FormatException e) {
2501d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               // Create an intent anyway, without NDEF messages
2502d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                               generateEmptyIntent = true;
2503b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2504b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       } else {
2505d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           // Create an intent anyway, without NDEF messages
2506d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           generateEmptyIntent = true;
2507d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       }
25083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2509d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                       if (generateEmptyIntent) {
2510d3c57c0c2419d595b8de940254814b5935932b28Martijn Coenen                           // Create an intent with an empty ndef message array
25113ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                           nativeTag.addNdefTechnology(null, supportedNdefLength, cardState);
25123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                           if (DBG) Log.d(TAG, "NDEF tag found, but length 0 or invalid format, " +
25133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                   "starting corresponding activity");
25143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                           dispatchNativeTag(nativeTag, new NdefMessage[] { });
2515b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2516f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   } else {
25173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2518f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2519f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else {
2520f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   Log.w(TAG, "Failed to connect to tag");
252121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                   nativeTag.disconnect();
2522f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2523f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
25243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2525f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2526ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2527f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
2528f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Send broadcast ordered */
2529f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TransactionIntent = new Intent();
2530f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
2531f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
2532ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
2533f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
2534f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2535f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2536f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2537f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2538f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2539f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2540f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2541f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2542ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2543f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2544f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2545f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2546f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2547f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2548ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2549eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2550eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2551eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2552eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2553eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2554b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2555b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2556f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2557ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2558f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2559b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2560eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
2561ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop.");
25624c631cd2aa3ab422d4f9f3404d6f1fabce7bdf4ddaniel_Tomas                       device.doDisconnect();
2563f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2564f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2565f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2566ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2567f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2568f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2569f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2570f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2571ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2572eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2573eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
25746f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2575ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2576f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2577b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2578f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2579f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2580f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2581eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2582eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2583eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2584cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2585ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "disconnecting from target");
2586cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   /* Restart polling loop */
2587cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton                   device.doDisconnect();
2588cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               } else {
2589ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "not disconnecting from initiator");
2590cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2591eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2592b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton               /* Mark the link state */
2593b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton               mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED;
2594b3cdb6612a057373a61521171d99ce4f24b84e1fJeff Hamilton
2595f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2596f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2597f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2598f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2599f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2600ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2601f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2602f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2603f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2604f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2605f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2606ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2607f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2608f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2609ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2610f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2611f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2612f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
261357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
261457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
261557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
261657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
261757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
261857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
261957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
262057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
262157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
262257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
262357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
262457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
262557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
262657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2627f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2628f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2629f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2630f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2631b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2632d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
26333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
26343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2635b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2636b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2637b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2638b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2639d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2640d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
26413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
26433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
26443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle());
26453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (dispatchTag(tag, msgs)) {
26463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                registerTagObject(nativeTag);
26473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            } else {
26483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
26493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
26533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
26543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
26563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
26583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
26593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
26613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
26623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
26643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
26673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
26683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
26703fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
26713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
26723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
26733fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
26743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
26753fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
26763fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
26773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
26783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
26793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
26803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
26833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
26843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
26853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            switch (tnf) {
26863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_MIME_MEDIA: {
26873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent.setType(new String(type, Charsets.US_ASCII));
26883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return true;
26893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
26903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_ABSOLUTE_URI: {
26913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
26923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return true;
26933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
26943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                case NdefRecord.TNF_WELL_KNOWN: {
26953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
26963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        intent.setType("text/plain");
26973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
26983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
26993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        // Parse the smart poster looking for the URI
27003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        try {
27013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            NdefMessage msg = new NdefMessage(record.getPayload());
27023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            for (NdefRecord subRecord : msg.getRecords()) {
27033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                if (subRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN
27043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                        && Arrays.equals(subRecord.getType(), NdefRecord.RTD_URI)) {
27053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                    intent.setData(parseWellKnownUriRecord(subRecord));
27063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                    return true;
27073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
27083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
27093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        } catch (FormatException e) {
27103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            return false;
27113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
27123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
27133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        intent.setData(parseWellKnownUriRecord(record));
27143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
27153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
27163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    return false;
27173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
27183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return false;
27203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
27213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri buildTechListUri(Tag tag) {
27233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int[] techList = tag.getTechnologyList();
27243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Arrays.sort(techList);
27253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Uri.Builder builder = new Uri.Builder();
27263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            builder.scheme("vnd.android.nfc").authority("tag");
27273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (int tech : techList) {
27283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                builder.appendPath(Integer.toString(tech));
27293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            builder.appendPath("");
27313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return builder.build();
27323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
27333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
27353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
27363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
27373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
27383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
27393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
27423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
27433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
27443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
27453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
27463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
27473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
27483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
27503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    setTypeOrDataFromNdef(intent, record);
27513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    try {
27533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        mContext.startActivity(intent);
27543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        // If an activity is found then skip further dispatching
27553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
27563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    } catch (ActivityNotFoundException e) {
27573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
27583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
27593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
27603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
27633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
27643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent.setData(buildTechListUri(tag));
27653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            try {
27663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                mContext.startActivity(intent);
27673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
27683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            } catch (ActivityNotFoundException e) {
27693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
27703fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
27733fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
27743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            try {
27753fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                mContext.startActivity(intent);
27763fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
27773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            } catch (ActivityNotFoundException e) {
27783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
27793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
27803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
2782b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2783b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2784b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
2785b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton
27867c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2787fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
27887c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
2789df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
2790161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2791161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
2792161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeEnableDiscovery();
2793161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
27947c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2795533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2796161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2797161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
2798161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeDisableDiscovery();
2799161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2800533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
28017c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
28027c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
28037c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
28047c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
28057c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
28060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
28070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
28080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2809eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2811ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
28120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2813f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
281465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                maybeEnableDiscovery();
2815f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
281665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
28177c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
28187c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
28197c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
28207c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2821df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(true));
282265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
28237c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
28247c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
28257c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
28267c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2827df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
2828f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
283174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2832