NfcService.java revision e260fc52ed2b4e6e1b7394d6f841d01c98888327
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;
2124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport com.android.nfc.RegisteredComponentCache.ComponentInfo;
22ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushClient;
23ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushServer;
24d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.Activity;
261a9eca5f84036d7dd3e28000290caa2f641856deNick Pellyimport android.app.ActivityManagerNative;
272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.app.IActivityManager;
2905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
30ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport android.app.PendingIntent.CanceledException;
3124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.app.StatusBarManager;
32b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
3924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo;
403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
41f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
42f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.INfcSecureElement;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
52f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
5624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
579d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
587c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
59b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
60b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
61b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
62533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
63f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
6413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
65f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
66f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
6857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
6957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
7157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
7324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
753ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
762436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.Timer;
780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomasimport java.util.TimerTask;
793ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
81ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
82fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
8357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
8457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
8513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
8613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
8713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
8813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
1003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
1013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
133d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
134fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
137bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
138bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
139bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
140bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
141bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
1480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean SECURE_ELEMENT_ON_DEFAULT = false;
149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
1510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int SECURE_ELEMENT_ID_DEFAULT = 0;
152f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
154e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
184a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
1950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
1990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
208b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
209b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
210b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
212b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
21357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
21457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
215b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
216c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
217c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
218b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
21905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    // Locked on mNfcAdapter
22005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    PendingIntent mDispatchOverrideIntent;
22124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    IntentFilter[] mDispatchOverrideFilters;
22224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    String[][] mDispatchOverrideTechLists;
22305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
22474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
22574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
22774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mSelectedSeId = 0;
2290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean mNfcSecureElementState;
230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    // Secure element
2320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private Timer mTimerOpenSmx;
2330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isClosed = false;
2340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean isOpened = false;
2350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private boolean mOpenSmxPending = false;
2360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
2370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private int mSecureElementHandle;
2380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2402f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2412f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
24265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
2432f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2442f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
24505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
2460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
249533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
2501a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly    private IActivityManager mIActivityManager;
251ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
252ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
25324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    RegisteredComponentCache mTechListFilters;
254d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
255d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
256d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
257d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
258d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
259d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2632f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2642f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
267d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
268d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
270b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
2710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
27274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
273ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
274ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
27557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
27624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        mTechListFilters = new RegisteredComponentCache(this,
27724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
27824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
2790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
2820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
284d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
286533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
28752028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
288533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
289533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
2901a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly        mIActivityManager = ActivityManagerNative.getDefault();
2911a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly
292d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
294eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
29565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
29665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
2970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
2980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
3000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
3040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3132f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3142f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3193ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3203ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3214acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
322fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
324d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
335fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
338d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
340ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
3436f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
344ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                mNdefPushServer.stop();
345e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
346e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // Stop watchdog if tag present
347e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // A convenient way to stop the watchdog properly consists of
348e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // disconnecting the tag. The polling loop shall be stopped before
349e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // to avoid the tag being discovered again.
350e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                maybeDisableDiscovery();
351e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                maybeDisconnectTarget();
352e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
3530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
354ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
3550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
357a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // Clear out any old dispatch overrides and NDEF push message
35805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (this) {
35905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
36005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
36105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
362a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    mNdefPushClient.setForegroundMessage(null);
3630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
371fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
37205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
37324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
374a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
37505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
376a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
377a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
378a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
379ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
380ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
381a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
382a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
383a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
384a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
385a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
386a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
387a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
388a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
389a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
390a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
391a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
392a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
393a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
394a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
39524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
39624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
39724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
39824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
39924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
40024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
40105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
402a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent != null) {
40305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "Replacing active dispatch overrides");
40405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
40505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = intent;
406a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = filters;
40724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                mDispatchOverrideTechLists = techLists;
40805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
40905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
41005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
41105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
41205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
41305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
41405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
415a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent == null) {
41605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "No active foreground dispatching");
41705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
41805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = null;
419a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = null;
42005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
42105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
42205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
42305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
424ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
425ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
426ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
427ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
428ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
429ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
430ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
431ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
432ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
433ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
434ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
435ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
436ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
437ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (!mNdefPushClient.setForegroundMessage(null)) {
438ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
439ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
440ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
441ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
442ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
444d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
445bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
450f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
4520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
4541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
4551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4571878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
4581878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4641878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4651878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4701878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4711878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4761878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
482fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
485d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
486bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
487f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
4930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4941878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
4951878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4961878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4981878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5001878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5051878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5141878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5151878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
519fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
522d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
523bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
526f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
528f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
5301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
531bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5341878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5391878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5401878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5411878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5461878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5471878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
5481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5521878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5561878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
559f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
560fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int deselectSecureElement() throws RemoteException {
562d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
564f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
565f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
566f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
567f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == 0) {
5700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NO_SE_CONNECTED;
571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
5720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doDeselectSecureElement(mSelectedSeId);
5740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = false;
5750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = 0;
5760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store preference */
5780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
5790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
5802f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
5810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
585fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
587d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
5890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
590bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
591fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
593d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
5950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
596f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
597fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
599d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
6010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
602f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
603fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
605d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
6070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
609fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
611d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
615fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
617d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public INfcSecureElement getNfcSecureElementInterface() {
6220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return mSecureElementService;
6240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
626fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
628d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
6480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
652f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
654f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
656f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
657fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int[] getSecureElementList() throws RemoteException {
659d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
660bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int[] list = null;
6620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mIsNfcEnabled == true) {
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                list = mManager.doGetSecureElementList();
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return list;
6660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
668fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getSelectedSecureElement() throws RemoteException {
670d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mSelectedSeId;
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
675fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
680fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void openTagConnection(Tag tag) throws RemoteException {
682b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // TODO: Remove obsolete code
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
685fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int selectSecureElement(int seId) throws RemoteException {
687d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
688f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
692f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
693f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId == seId) {
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mSelectedSeId != 0) {
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SE_CONNECTED;
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mSelectedSeId = seId;
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mManager.doSelectSecureElement(mSelectedSeId);
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* store */
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
7082f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick            mPrefsEditor.apply();
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = true;
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
716fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
718d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
7402f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
7542f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
7580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
7600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
7682f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
7822f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
7922f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
8022f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
8122f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
8222f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
8322f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
837f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
839f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
842f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
843d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
844d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
845d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
84657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
84757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
84857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
84957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
85057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
851d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
852d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
853d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
854d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
85557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
85657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
85757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
85857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
85957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
86057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
86257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
86357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
86457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
86557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
86757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
86857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
86957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
87057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
87157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
87257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
87357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
87457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
87557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
87657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
87757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
87857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
87957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
88057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
88157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
88257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
88357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
88457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
88557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
88657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
88757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
88857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
88957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
89057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
89157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
89257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
89357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
89457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
89557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
896d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
900f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
901f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
902bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
903bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
904f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
905f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
906bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
907f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
908f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
909fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
911d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
912bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
914f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
921f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
9241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
9251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
9261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
930f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
932fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
934d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
935bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
940f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
945f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
94793915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
9480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
9490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
959fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
961d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
962bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
972f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
97493915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
986fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
988d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
989bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
9970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
998f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1006fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1008d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1009bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
10140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1018f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
10210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1026fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1028d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1029bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1034f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1038f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
10410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
10430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1046fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1048d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1058f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
10610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1070fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1072d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1082f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
10850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
10860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1094fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1096d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1106f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
110828f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
111028f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
11110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1114fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1116d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1127f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
11300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
11310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
11320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
11420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1143f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
1144bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1145bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
1146f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1147f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1148bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
1149f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1150f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1151fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1153d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
11570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
1164f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
116693915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
11680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
11690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
11702f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
11711878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
11721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
11731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
11742f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
11750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
11760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
11770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
11780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1183fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1185d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
11920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1195f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
1198f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
11990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
12000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
12010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1208f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
1209bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1210bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
1211f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1212f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1213bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
1214f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1215f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1216fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1219bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1228f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
12301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
12311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
12321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1236fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1238d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1239bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1248f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1256fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1258d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1259bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1269f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1281fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1283d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1284bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1294f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1310fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1313bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1324b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1325b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
132621545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1327b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
133065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
1331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1334fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1335ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1336d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1337bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1347b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1348b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1350ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
1351ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1352ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1353ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1354ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1355ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1356ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1357ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1358ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1361fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1362aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1363aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1364aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1365aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1366aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1367aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1368aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1369aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1370aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1371aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1372aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1373aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1374aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1375aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1376aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1377aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1378aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1379aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1380aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1381aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1382aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1383aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1384aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1385b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1386d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1387bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1394b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1396b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1401fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1420fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1421b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1422b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1423b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1424b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1425b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1426b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1427b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1428b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1429b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1430b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1431b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1432b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1433b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1434b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1435b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            return tag.presenceCheck();
1436b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1437b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1438fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1444f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
14503ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1451f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14523ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1455f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1457fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14589d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
145997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1460d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1461bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14739d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
14749d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
14759d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
14769d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
14779d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
14789d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
14799d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1484fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1486d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1487bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1492f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1493f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1498b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1501f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1507f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1509f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1510f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1511f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1512fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1514d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1515bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1521f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1522f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1526f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1528f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1529b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1535f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1538fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1539f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1540bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1543fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
15453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1548fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
155003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
155103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
155203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
155303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
155403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
155503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
155603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
155703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
155803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
155903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
156003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
156103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
156203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
156303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
156403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
156503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
156603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
156703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
156803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
156903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
157003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
15740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
15750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
15780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
15800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
15810aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
15820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
15850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
15870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
15910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
15920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
15940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
15970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15981b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
15991b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
16001b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16011b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
16021b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
16031b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16051b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
16061b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void resetIsoDepTimeout() throws RemoteException {
16071b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16081b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
16091b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.resetIsoDepTimeout();
16101b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
16110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1612f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1615fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1617d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1618f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1636f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1637fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1639d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1640f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1654f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1656fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(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.doReceive();
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
167665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1682d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1686f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
16960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1700f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1703fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1705d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1706f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1708f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
17190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
17200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
17220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1723f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1724fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1726d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1730f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1735f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1741b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
174365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                    maybeEnableDiscovery();
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1745f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
17460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1747f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1750fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1752d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1753f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
17560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1759f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1760f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1771f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1772fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1774d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1775f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1777f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1781f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1782f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
17890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1790f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1791fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
179297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
179397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1794d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1795f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1797f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1801f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1802f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
18130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1814f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() {
18160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int openSecureElementConnection() throws RemoteException {
18180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            Log.d(TAG, "openSecureElementConnection");
18190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int handle;
18200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check in an open is already pending
18270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mOpenSmxPending) {
18280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return 0;
18290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            handle = mSecureElement.doOpenSecureElementConnection();
18320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (handle == 0) {
18340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
18360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mSecureElementHandle = handle;
18370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Start timer */
18390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx = new Timer();
18400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
18410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = true;
18440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = false;
18450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = true;
18460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return handle;
18490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int closeSecureElementConnection(int nativeHandle)
18520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
18530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
18550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
18560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_NOT_INITIALIZED;
18570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
18600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
18610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
18620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
18650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
18660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return -1;
18670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElement.doDisconnect(nativeHandle)) {
18700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
18720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
18730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
18750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
18760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
18790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
18800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.SUCCESS;
18830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            } else {
18840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Stop timer */
18860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mTimerOpenSmx.cancel();
18870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Restart polling loop for notification */
18890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mManager.enableDiscovery(DISCOVERY_MODE_READER);
18900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                /* Update state */
18920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isOpened = false;
18930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                isClosed = true;
18940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                mOpenSmxPending = false;
18950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
18960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return ErrorCodes.ERROR_DISCONNECT;
18970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public int[] getSecureElementTechList(int nativeHandle)
19010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            int[] techList = mSecureElement.doGetTechList(nativeHandle);
19180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return techList;
19250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] getSecureElementUid(int nativeHandle)
19280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] uid;
19300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19340bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            uid = mSecureElement.doGetUid(nativeHandle);
19470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19500bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return uid;
19540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public byte[] exchangeAPDU(int nativeHandle, byte[] data)
19570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                throws RemoteException {
19580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            byte[] response;
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if NFC is enabled
19610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!mIsNfcEnabled) {
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is closed
19660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (isClosed) {
19670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            // Check if the SE connection is opened
19710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (!isOpened) {
19720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                return null;
19730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            response = mSecureElement.doTransceive(nativeHandle, data);
19760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            /* Stop and Restart timer */
19780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.cancel();
19790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx = new Timer();
19800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000);
19810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            return response;
19830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
19860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    class TimerOpenSecureElement extends TimerTask {
19880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        @Override
19900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        public void run() {
19910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            if (mSecureElementHandle != 0) {
19920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                Log.d(TAG, "Open SMX timer expired");
19930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
19940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                    mSecureElementService
19950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                            .closeSecureElementConnection(mSecureElementHandle);
19960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                } catch (RemoteException e) {
19970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                }
19980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
20030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
20056efda9f3970382554437be037aed863be9889499Sylvain Fonteneau        applyProperties();
20066efda9f3970382554437be037aed863be9889499Sylvain Fonteneau
20070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
20080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
20090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check Secure Element setting */
20100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON,
20110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    SECURE_ELEMENT_ON_DEFAULT);
2012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (mNfcSecureElementState) {
20140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID,
20150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        SECURE_ELEMENT_ID_DEFAULT);
20160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                int[] Se_list = mManager.doGetSecureElementList();
20170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (Se_list != null) {
20180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    for (int i = 0; i < Se_list.length; i++) {
20190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        if (Se_list[i] == secureElementId) {
20200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mManager.doSelectSecureElement(Se_list[i]);
20210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            mSelectedSeId = Se_list[i];
20220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            break;
20230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        }
20240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
20250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
2026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
202865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
202965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
203165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            maybeEnableDiscovery();
203257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
203357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
2034ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
203557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
20370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
2038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
2041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
2043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
204565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Enable active tag discovery if screen is on and NFC is enabled */
204665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeEnableDiscovery() {
204765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mScreenOn && mIsNfcEnabled) {
204865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.enableDiscovery(DISCOVERY_MODE_READER);
204965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
205065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
205165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
205265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    /** Disable active tag discovery if necessary */
205365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private synchronized void maybeDisableDiscovery() {
205465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        if (mIsNfcEnabled) {
205565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mManager.disableDiscovery();
205665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
205765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
205865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20592436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
20602436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
20612436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
20622436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
20632436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
20642436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
2065663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
2066663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
20672436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
20682436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
20692436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
2070663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
2071663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
2072663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
2073663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2074663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
2075663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
2076663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2077663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
2078663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
2079663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
2080663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2081663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
2082663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
20832436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
20842436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
20852436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
20862436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
2087f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2088f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2089f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2090f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2091f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2092f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2093f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2094f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2095f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2096f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2097f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2098f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2099f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2100f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2101f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2102f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2103f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
21050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
21062f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
21070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
21082f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
21094acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
21102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
21114acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
21122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
21132f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
21142f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
211557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
211657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
211757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
211857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
211957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
212057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
212157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
212257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
212357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
212457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
212557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
212657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
212757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
212857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
212957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
213057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
213157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
213257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
213357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
213457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
213557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
213657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
213757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
213857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
213957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
214057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
214157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
214257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
214357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
214457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
214557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
214657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
214757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
214857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
214957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
215057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
215157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
215257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
215357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
215457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
215557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
215757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
215857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
215957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
216057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
216157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
21640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2165f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
21682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
216974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
217074180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSelectedSeId = 0;
2179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21812f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
21922f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2193b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2194b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2195b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
21962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2197b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2201bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2202bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2203bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2204bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2211d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2212d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2213d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2214d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
22151be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22161be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22171be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22181be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2219d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2220d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2221d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2222d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2223d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2224d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2225d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2226d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2227d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2228d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2229d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2230d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
22311be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22321be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22331be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22341be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2235d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2236d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2237d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2238d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2239d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2240d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2241d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
22420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
22430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
22440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
22450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
22480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2250ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
22510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
22520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
225457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2255b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
225657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
225757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2258b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2259b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2260b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2261b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2262b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2263b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2264b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2265b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2266232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2267232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
2268232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            // Try to find NDEF on any of the technologies.
2269232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] technologies = nativeTag.getTechList();
2270232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] handles = nativeTag.getHandleList();
2271232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int techIndex = 0;
2272232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int lastHandleScanned = 0;
2273232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            boolean ndefFoundAndConnected = false;
2274232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            NdefMessage[] ndefMsgs = null;
2275eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen            boolean foundFormattable = false;
2276e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableHandle = 0;
2277e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableTechnology = 0;
2278232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2279232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
2280232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                if (handles[techIndex] != lastHandleScanned) {
2281232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    // We haven't seen this handle yet, connect and checkndef
2282232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    if (nativeTag.connect(technologies[techIndex])) {
2283eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        // Check if this type is NDEF formatable
2284434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        if (!foundFormattable) {
2285434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            if (nativeTag.isNdefFormatable()) {
2286434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                foundFormattable = true;
2287434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableHandle = nativeTag.getConnectedHandle();
2288434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableTechnology = nativeTag.getConnectedTechnology();
2289434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // We'll only add formattable tech if no ndef is
2290434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // found - this is because libNFC refuses to format
2291434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // an already NDEF formatted tag.
2292434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            }
2293434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            nativeTag.reconnect();
2294434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        } // else, already found formattable technology
2295434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen
2296232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        int[] ndefinfo = new int[2];
2297232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        if (nativeTag.checkNdef(ndefinfo)) {
2298232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            ndefFoundAndConnected = true;
2299232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            boolean generateEmptyNdef = false;
2300232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2301232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int supportedNdefLength = ndefinfo[0];
2302232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int cardState = ndefinfo[1];
2303232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            byte[] buff = nativeTag.read();
2304232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            if (buff != null) {
2305232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                ndefMsgs = new NdefMessage[1];
2306232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                try {
2307232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    ndefMsgs[0] = new NdefMessage(buff);
2308232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.addNdefTechnology(ndefMsgs[0],
2309ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                            nativeTag.getConnectedHandle(),
23100a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                            nativeTag.getConnectedLibNfcType(),
2311f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                            nativeTag.getConnectedTechnology(),
2312232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                            supportedNdefLength, cardState);
2313232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.reconnect();
2314232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                } catch (FormatException e) {
2315232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   // Create an intent anyway, without NDEF messages
2316232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   generateEmptyNdef = true;
2317232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                }
2318232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            } else {
2319232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                generateEmptyNdef = true;
2320232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
2321232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2322232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           if (generateEmptyNdef) {
2323232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               ndefMsgs = new NdefMessage[] { };
2324ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                               nativeTag.addNdefTechnology(null,
2325ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       nativeTag.getConnectedHandle(),
23260a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                       nativeTag.getConnectedLibNfcType(),
2327f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                       nativeTag.getConnectedTechnology(),
2328ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       supportedNdefLength, cardState);
2329232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               nativeTag.reconnect();
2330232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           }
2331232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        } // else, no NDEF on this tech, continue loop
2332232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    } else {
2333232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // Connect failed, tag maybe lost. Try next handle
2334232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // anyway.
2335232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    }
2336232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2337232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                lastHandleScanned = handles[techIndex];
2338232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                techIndex++;
2339232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            }
2340e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            if (ndefMsgs == null && foundFormattable) {
2341e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // Tag is not NDEF yet, and found a formattable target,
2342e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // so add formattable tech to tech list.
2343e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                nativeTag.addNdefFormatableTechnology(
2344e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableHandle,
2345e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableTechnology);
2346e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
2347232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2348232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            return ndefMsgs;
2349232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
2350232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2351b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2352b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2353f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2354b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2355b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2356b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2357b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2358b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
235957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
236057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
23613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
236257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
236357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
236457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2365f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2366ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2367f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2368232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2369232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2370232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
237198eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2372232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2373232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2374232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2375232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
237698eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
23773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2378232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2379232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2380232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2381f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2382f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2383f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
23843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2385f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2386ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2387f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
2388f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Send broadcast ordered */
2389f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TransactionIntent = new Intent();
2390f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED);
2391f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid);
2392ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Card Emulation event");
2393f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM);
2394f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2395f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2396f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2397f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2398f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2399f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2400f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2401f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2402ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2403f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2404f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2405f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2406f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2407f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2408ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2409663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2410663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2411eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2412eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2413eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2414eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2415eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2416b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2417b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2418f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2419ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2420f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2421b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2422eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
24237f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
24247f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2425f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2426f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2427f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2428ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2429f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2430f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2431f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2432f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2433ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2434663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2435663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2436eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2437eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
24386f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2439ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2440f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2441b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2442f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2443f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2444f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2445eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2446eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2447eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2448663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2449663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2450663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2451663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2452663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2453663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2454663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2455663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2456663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2457663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2458663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2459663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2460cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2461eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2462f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2463f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2464f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2465f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2466f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2467ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2468f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2469f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2470f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2471f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2472f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2473ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2474f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2475f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2476ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2477f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2478f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2479f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
248057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
248157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
248257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
248357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
248457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
248557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
248657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
248757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
248857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
248957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
249057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
249157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
249257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
249357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2494c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2495c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2496c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
2497c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               eventFieldOnIntent.setAction(NfcAdapter.ACTION_RF_FIELD_ON_DETECTED);
2498c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
2499c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               mContext.sendBroadcast(eventFieldOnIntent, NFC_PERM);
2500c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2501c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2502c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2503c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2504c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2505c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
2506c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               eventFieldOffIntent.setAction(NfcAdapter.ACTION_RF_FIELD_OFF_DETECTED);
2507c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
2508c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               mContext.sendBroadcast(eventFieldOffIntent, NFC_PERM);
2509c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2510c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2511c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2512f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2513f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2514f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2515f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2516b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2517d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
25183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
25193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2520b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2521b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2522b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2523b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2524d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2525d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
25263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
25283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
25290c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
25303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (dispatchTag(tag, msgs)) {
25313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                registerTagObject(nativeTag);
25323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            } else {
25333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
25343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
25383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
25393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
25403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
25413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
25433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
25443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
25453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
25463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
25473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
25493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
25523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
25533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
25553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
25563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
25573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
25583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
25593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
25603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
25613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
25623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
25633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
25643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
25653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
25683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
25693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
2570adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            try {
2571adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                switch (tnf) {
2572adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_MIME_MEDIA: {
2573adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setType(new String(type, Charsets.US_ASCII));
25743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
2575adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
2576adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_ABSOLUTE_URI: {
2577adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setData(Uri.parse(new String(record.getPayload(), Charsets.UTF_8)));
2578adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return true;
2579adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
2580adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_WELL_KNOWN: {
2581adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        byte[] payload = record.getPayload();
2582adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (payload == null || payload.length == 0) return false;
2583adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
2584adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setType("text/plain");
2585adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2586adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
2587adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // Parse the smart poster looking for the URI
2588adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            try {
2589adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                NdefMessage msg = new NdefMessage(record.getPayload());
2590adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                for (NdefRecord subRecord : msg.getRecords()) {
2591adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    short subTnf = subRecord.getTnf();
2592adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    if (subTnf == NdefRecord.TNF_WELL_KNOWN
2593adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                            && Arrays.equals(subRecord.getType(),
2594adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                    NdefRecord.RTD_URI)) {
2595adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(parseWellKnownUriRecord(subRecord));
2596adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2597adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) {
2598adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(Uri.parse(new String(subRecord.getPayload(),
2599adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                Charsets.UTF_8)));
2600adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2601adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    }
26023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
2603adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            } catch (FormatException e) {
2604adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                return false;
26053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
2606adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
2607adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setData(parseWellKnownUriRecord(record));
2608adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
26093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
2610adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return false;
26113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
26123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
2613adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
2614adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            } catch (Exception e) {
2615adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                Log.e(TAG, "failed to parse record", e);
2616adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
26173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
26213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
26223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
26233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
26243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
26253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
262705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            IntentFilter[] overrideFilters;
262805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            PendingIntent overrideIntent;
262924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] overrideTechLists;
2630a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            boolean foregroundNdefPush = mNdefPushClient.getForegroundMessage() != null;
263105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (mNfcAdapter) {
263205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideFilters = mDispatchOverrideFilters;
263305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideIntent = mDispatchOverrideIntent;
263424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                overrideTechLists = mDispatchOverrideTechLists;
263505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
263605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
263705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // First look for dispatch overrides
2638a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (overrideIntent != null) {
263905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
264005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
264124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters,
264224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideTechLists)) {
264305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        if (DBG) Log.d(TAG, "Dispatched to override");
264405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
264505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
264605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch override registered, but no filters matched");
264705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (CanceledException e) {
264805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
264905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (mNfcAdapter) {
265005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
265105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
265224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mDispatchOverrideTechLists = null;
265305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
265405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
265505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
265605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
2657a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // If there is not foreground NDEF push setup try a normal dispatch.
2658a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            //
2659a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // This is avoided when disabled in the NDEF push case to avoid the situation where each
2660a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // user has a different app in the foreground, causing each to launch itself on the
2661a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // remote device and the apps swapping which is in the foreground on each phone.
2662a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (!foregroundNdefPush) {
2663a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                try {
266424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return dispatchTagInternal(tag, msgs, null, null, null);
2665a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } catch (CanceledException e) {
2666a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.e(TAG, "CanceledException unexpected here", e);
2667a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2668a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
266905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
2670a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2671a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            return false;
267205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
267305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
267424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        /** Returns true if the tech list filter matches the techs on the tag */
267524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        private boolean filterMatch(String[] tagTechs, String[] filterTechs) {
267624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (filterTechs == null || filterTechs.length == 0) return false;
267724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
267824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            for (String tech : filterTechs) {
267924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (Arrays.binarySearch(tagTechs, tech) < 0) {
268024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return false;
268124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
268224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
268324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            return true;
268424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        }
268524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
268605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        // Dispatch to either an override pending intent or a standard startActivity()
268705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
268824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                PendingIntent overrideIntent, IntentFilter[] overrideFilters,
268924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                String[][] overrideTechLists)
269005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                throws CanceledException{
26913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
269224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
269324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
269424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Try the NDEF content specific dispatch
269524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
26963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
26973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
26983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
26993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
27003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
27013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
27023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
2704adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    if (setTypeOrDataFromNdef(intent, record)) {
2705adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        // The record contains filterable data, try to start a matching activity
270624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (startDispatchActivity(intent, overrideIntent, overrideFilters,
270724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                                overrideTechLists)) {
2708adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // If an activity is found then skip further dispatching
2709adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2710adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else {
2711adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
2712adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        }
27133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
27143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
27153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
271724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
271924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
272024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[] tagTechs = tag.getTechList();
272124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            Arrays.sort(tagTechs);
272224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
272324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (overrideIntent != null) {
272424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // There are dispatch overrides in place
272524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideTechLists != null) {
272624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    for (String[] filterTechs : overrideTechLists) {
272724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (filterMatch(tagTechs, filterTechs)) {
272824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            // An override matched, send it to the foreground activity.
272924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            intent = buildTagIntent(tag, msgs,
273024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                                    NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
273124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideIntent.send(mContext, Activity.RESULT_OK, intent);
273224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            return true;
273324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        }
273424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
273524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
273605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
273724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Standard tech dispatch path
273824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
273924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ComponentInfo> registered = mTechListFilters.getComponents();
274024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
274124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Check each registered activity to see if it matches
274224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                for (ComponentInfo info : registered) {
274324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Don't allow wild card matching
274424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (filterMatch(tagTechs, info.techs)) {
274524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        matches.add(info.resolveInfo);
274624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
274724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
274824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
274924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (matches.size() == 1) {
275024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Single match, launch directly
275124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED);
275224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    ResolveInfo info = matches.get(0);
275324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
275424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
275524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
275624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
275724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
275824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
275924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
276024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (matches.size() > 1) {
276124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Multiple matches, show a custom activity chooser dialog
276224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent = new Intent(mContext, TechListChooserActivity.class);
276324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
276424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putExtra(Intent.EXTRA_INTENT,
276524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED));
276624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
276724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            matches);
276824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
276924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
277024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
277124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
277224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
277324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
277424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else {
277524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // No matches, move on
277624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
277724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
27783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
278024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
278224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
278424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters, overrideTechLists)) {
27853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
278605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
27873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
27883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
27893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
279105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
279205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
279324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] overrideFilters, String[][] overrideTechLists)
279424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                throws CanceledException {
279505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideIntent != null) {
2796a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                boolean found = false;
279724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideFilters == null && overrideTechLists == null) {
2798a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // No filters means to always dispatch regardless of match
2799a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    found = true;
280024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (overrideFilters != null) {
2801a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : overrideFilters) {
2802a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
2803a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            found = true;
2804a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            break;
2805a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
280605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
280705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
2808a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2809a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (found) {
2810a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.i(TAG, "Dispatching to override intent " + overrideIntent);
2811a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    overrideIntent.send(mContext, Activity.RESULT_OK, intent);
2812a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return true;
2813a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
2814a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2815a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
281605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
281705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
28181a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // If the current app called stopAppSwitches() then our startActivity()
28191a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // can be delayed for several seconds. This happens with the default home
28201a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // screen. As a system service we can override this behavior with
28211a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // resumeAppSwitches()
28221a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    mIActivityManager.resumeAppSwitches();
28231a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                } catch (RemoteException e) { }
28241a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                try {
282505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    mContext.startActivity(intent);
282605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return true;
282705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (ActivityNotFoundException e) {
282805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return false;
282905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
283005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
283105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
2832b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2833b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2834b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
2835b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton
28367c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2837fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
28387c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
2839df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
2840161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2841161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
2842161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeEnableDiscovery();
2843161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
28447c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2845533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2846161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2847161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
2848161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    maybeDisableDiscovery();
28492436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    maybeDisconnectTarget();
2850161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2851533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
28527c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
28537c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
28547c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
28557c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
28567c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
28570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
28580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
28590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2860eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2861f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2862ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
28630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2864f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
286565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly                maybeEnableDiscovery();
2866f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
286765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
28687c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
28697c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
28707c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
28717c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2872df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(true));
287365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
28747c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
28757c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
28767c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
28777c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2878df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
2879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2881f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
288274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2883