NfcService.java revision 3fb14d0868594c78a777e805545209636814e223
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;
248afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R;
25d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.Activity;
271a9eca5f84036d7dd3e28000290caa2f641856deNick Pellyimport android.app.ActivityManagerNative;
282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.app.IActivityManager;
30275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager;
3105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
3293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.app.PendingIntent.CanceledException;
33bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.app.StatusBarManager;
34b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
4224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo;
43160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenenimport android.content.pm.PackageManager;
443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
45bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.nfc.ApduList;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
512094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5349d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
58f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
60f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
623fb14d0868594c78a777e805545209636814e223Martijn Coenenimport android.nfc.tech.TagTechnology;
6324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
649d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
651b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenenimport android.nfc.tech.TagTechnology;
667c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
67b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
68b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6949d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
70b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
71533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
7313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
74f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
75f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
77bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
78bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataOutputStream;
7957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
8057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
8157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
8257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
8424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
863ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
872436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
88bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
893ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
91bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
92bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
93ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
94fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
96a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
9813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
9913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
10013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
10113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
146d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
147fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
150bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
151bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
152bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
153bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
154a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
15593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
156bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
157225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen    /*package*/ static final String PREF = "NfcServicePrefs";
158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
162a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
163a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
165e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
195a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
2040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
2060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
2100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
219b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
220b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
221b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
222b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
223b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
22457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
22557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
226b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
227c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
228c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
229b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
23049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
23149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
23249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
23349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
23449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
23549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
23649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
23749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
23849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
23949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
24049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
24149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
24205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    // Locked on mNfcAdapter
24305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    PendingIntent mDispatchOverrideIntent;
24424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    IntentFilter[] mDispatchOverrideFilters;
24549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    String[][] mDispatchOverrideTechLists;
24605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
24774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
24874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
25074180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
25149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
25249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
25349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
25449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
25549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private static final int SECURE_ELEMENT_ID = 11259375;  //TODO: remove hard-coded value
2560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
25749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
25849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
2590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2602f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2612f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2622f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
263275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private boolean mScreenUnlocked;
264a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private String mSePackageName;
2652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
26705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
2680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
271533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
2721a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly    private IActivityManager mIActivityManager;
273ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
274ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
27524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    RegisteredComponentCache mTechListFilters;
276275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private KeyguardManager mKeyguard;
277d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
278d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
279d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
28093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
28193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
28293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
28393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
28493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
28593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
28693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
28793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
28893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
28993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
29093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
29193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
29293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
293d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
294d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
295d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
297160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen    private static boolean isComponentEnabled(PackageManager pm, ResolveInfo info) {
298160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        boolean enabled = false;
299160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        ComponentName compname = new ComponentName(
300160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen                info.activityInfo.packageName, info.activityInfo.name);
301160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        try {
302160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            // Note that getActivityInfo() will internally call
303160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            // isEnabledLP() to determine whether the component
304160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            // enabled. If it's not, null is returned.
305160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            if (pm.getActivityInfo(compname,0) != null) {
306160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen                enabled = true;
307160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            }
308160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        } catch (PackageManager.NameNotFoundException e) {
309160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            enabled = false;
310160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        }
311160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        if (!enabled) {
312160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen            Log.d(TAG, "Component not enabled: " + compname);
313160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        }
314160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen        return enabled;
315160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen    }
316160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen
3170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
3192f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
3202f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
3212f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
3222f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
323d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
324d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
326275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mManager = new NativeNfcManager(this, this);
3270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
32874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
329ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
330ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
33157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
33224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        mTechListFilters = new RegisteredComponentCache(this,
3338d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
33424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
3350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
3360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
337275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
3380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
340d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
342275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
343275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
344533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
345275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
346275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
347533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
3481a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly        mIActivityManager = ActivityManagerNative.getDefault();
3491a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly
350d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
352eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
35365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
35465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
355bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
356275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        filter.addAction(Intent.ACTION_USER_PRESENT);
357275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
358bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
359bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
360bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
361bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
362bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
363275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
3640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
3700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
372a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3812f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3863ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3873ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3884acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
389fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
39193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
402fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
4040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
40593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
4060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
407ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
4080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
4106f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
411ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                mNdefPushServer.stop();
412e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
413e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // Stop watchdog if tag present
414e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // A convenient way to stop the watchdog properly consists of
415e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // disconnecting the tag. The polling loop shall be stopped before
416e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // to avoid the tag being discovered again.
41749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mIsDiscoveryOn = false;
41849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
419e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                maybeDisconnectTarget();
420e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
4210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
422ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
4230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
4240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
425a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // Clear out any old dispatch overrides and NDEF push message
42605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (this) {
42705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
42805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
42905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
430a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    mNdefPushClient.setForegroundMessage(null);
4310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
4330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
4350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
439fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
44005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
44124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
442a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
44305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
444a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
445a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
446a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
447ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
448ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
449a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
450a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
451a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
452a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
453a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
454a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
455a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
456a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
457a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
458a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
459a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
460a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
461a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
462a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
46324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
46424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
46524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
46624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
46724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
46849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
46905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
470a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent != null) {
47105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "Replacing active dispatch overrides");
47205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
47305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = intent;
474a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = filters;
47524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                mDispatchOverrideTechLists = techLists;
47605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
47705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
47805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
47905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
48005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
48105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
48205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
483a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent == null) {
48405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "No active foreground dispatching");
48505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
48605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = null;
487a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = null;
48805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
48905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
49005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
49105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
492ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
493ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
494ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
495ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
496ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
497ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
498ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
499ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
500ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
501ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
502ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
5032094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
5042094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
5052094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5062094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
5072094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
5082094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
5092094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (mNdefPushClient.setForegroundCallback(callback)) {
5102094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
5112094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
5122094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
5132094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
5142094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
515ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
516ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5172094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadMsg = mNdefPushClient.setForegroundMessage(null);
5182094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadCallback = mNdefPushClient.setForegroundCallback(null);
5192094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
520ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
521ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
522ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
523ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
524ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
5250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
526d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
527bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
528f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
5340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
5361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
5371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
538f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5391878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
5401878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5411878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5421878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5461878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5471878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5521878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5561878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5571878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5581878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
561f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
564fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
567d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
568bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
569f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
570f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
5750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5761878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
5771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5791878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5801878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5821878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
585f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
586f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5871878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5881878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5891878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5901878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5911878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5931878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5941878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5951878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5961878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
599f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
601fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
6030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
604d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
605bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
606f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
607f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
608f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
609f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
610f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
6121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
613bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6141878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
615f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
6171878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
6181878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
6191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
6221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
6231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
6240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
6271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
6281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
6301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
6321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
6331878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
6341878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
6351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
6361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
6371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
6381878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
640f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
641f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
642fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
644d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
647bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
648fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
650d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
654fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
656d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
660fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
662d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
666fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
668d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
672fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
674d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
678bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
67949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
68093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
68149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
6820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
684fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
686d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
710f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
712f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
715fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
720fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
72293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
7442f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
7582f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
7722f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
7862f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
7962f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
8062f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
8162f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
8220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
8262f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
8362f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
841f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
843f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
846f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
847d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
848d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
849d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
85057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
85157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
85257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
85357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
85457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
855d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
856d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
857d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
858d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
85993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
86057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
86257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
86357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
86457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
86657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
86757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
86857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
86957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
87057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
87157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
87257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
87357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
87457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
87557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
87657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
87757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
87857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
87957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
88057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
88157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
88257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
88357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
88457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
88557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
88657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
88757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
88857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
88957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
89057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
89157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
89257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
89357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
89457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
89557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
89657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
89757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
89857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
89957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
900d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
9013fb14d0868594c78a777e805545209636814e223Martijn Coenen
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
9030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
905f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
906f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
907bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
908bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
909f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
910f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
911bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
912f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
913f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
914fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
916d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
917bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
921f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
923f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
924f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
926f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
9291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
9301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
9311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
934f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
937fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
939d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
940bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
950f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
95293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
9530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
9540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
964fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
966d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
967bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
977f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
97993915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
991fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
993d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
994bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1003f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
1006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
10070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1011fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
1013d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1014bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
10190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1022f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1023f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1031fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1033d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1034bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1042f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1043f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
10460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
10480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1051fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1053d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1063f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1075fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1077d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1087f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
10900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1099fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1101d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1111f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
111328f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
11140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
111528f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
11160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1119fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1121d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
11250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1132f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
11350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
11420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
11450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
11470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1148f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
1149bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1150bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
1151f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1152f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1153bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
1154f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1155f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1156fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1158d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
1169f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
11700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
117193915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
11720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
11730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
11740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
11752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
11761878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
11771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
11781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
11792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
11820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
11830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1188fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1190d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
11970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1200f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
12010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
12021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
1203f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
12040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
12050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
12060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
12070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
12080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1213f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
1214bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1215bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
1216f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1217f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1218bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
1219f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1220f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1221fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1223d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1224bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1233f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
12351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
12361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
12371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1241fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1243d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1244bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1253f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1261fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1263d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1264bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1274f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1286fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1288d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1289bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1299f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1315fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1317d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1318bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1329b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1330b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
133121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1332b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
133549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1339fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1340ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1341d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1342bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1352b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1353b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1355ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
13561b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            if (technology == TagTechnology.NFC_B) {
13571b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen                return ErrorCodes.ERROR_NOT_SUPPORTED;
13581b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            }
13591b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen
1360ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1361ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1362ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1363ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1364ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1365ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1366ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1367ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1370fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1371aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1372aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1373aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1374aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1375aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1376aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1377aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1378aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1379aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1380aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1381aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1382aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1383aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1384aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1385aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1386aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1387aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1388aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1389aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1390aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1391aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1392aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1393aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1394b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1395d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1396bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1403b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1405b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1410fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1429fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1430b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1431b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1432b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1433b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1434b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1435b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1436b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1437b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1438b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1439b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1440b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1441b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1442b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1443b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1444ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1445b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1446b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1447fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1450f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1451f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1455f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1457f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
14593ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14613ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1466fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14679d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
146897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1469d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1470bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1477f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14829d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
14839d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
14849d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
14859d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
14869d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
14879d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
14889d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1492f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1493fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1495d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1496bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1501f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1507b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1509f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1510f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1511f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1512f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1514f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1521fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1523d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1524bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1526f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1528f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1535f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1538b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1539f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1540f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1544f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1547fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1549bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1551f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1552fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
15543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1557fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
155903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
156003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
156103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
156203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
156303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
156403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
156503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
156603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
156703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
156803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
156903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
157003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
157103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
157203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
157303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
157403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
157503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
157603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
157703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
157803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
157903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1581f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
15830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
15840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
15870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
15890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
15900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
15910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
15940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
15960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15980aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15990aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
16000aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
16010aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16020aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
16030aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
16040aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
16050aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
16060aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
16071b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
16083fb14d0868594c78a777e805545209636814e223Martijn Coenen        public Tag rediscover(int nativeHandle) throws RemoteException {
16093fb14d0868594c78a777e805545209636814e223Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16103fb14d0868594c78a777e805545209636814e223Martijn Coenen
16113fb14d0868594c78a777e805545209636814e223Martijn Coenen            NativeNfcTag tag = null;
16123fb14d0868594c78a777e805545209636814e223Martijn Coenen
16133fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Check if NFC is enabled
16143fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (!mIsNfcEnabled) {
16153fb14d0868594c78a777e805545209636814e223Martijn Coenen                return null;
16163fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
16173fb14d0868594c78a777e805545209636814e223Martijn Coenen
16183fb14d0868594c78a777e805545209636814e223Martijn Coenen            /* find the tag in the hmap */
16193fb14d0868594c78a777e805545209636814e223Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
16203fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (tag != null) {
16213fb14d0868594c78a777e805545209636814e223Martijn Coenen                // For now the prime usecase for rediscover() is to be able
16223fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to access the NDEF technology after formatting without
16233fb14d0868594c78a777e805545209636814e223Martijn Coenen                // having to remove the tag from the field, or similar
16243fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to have access to NdefFormatable in case low-level commands
16253fb14d0868594c78a777e805545209636814e223Martijn Coenen                // were used to remove NDEF. So instead of doing a full stack
16263fb14d0868594c78a777e805545209636814e223Martijn Coenen                // rediscover (which is poorly supported at the moment anyway),
16273fb14d0868594c78a777e805545209636814e223Martijn Coenen                // we simply remove these two technologies and detect them
16283fb14d0868594c78a777e805545209636814e223Martijn Coenen                // again.
16293fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF);
16303fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
16313fb14d0868594c78a777e805545209636814e223Martijn Coenen                NdefMessage[] msgs = findAndReadNdef(tag);
16323fb14d0868594c78a777e805545209636814e223Martijn Coenen                // Build a new Tag object to return
16333fb14d0868594c78a777e805545209636814e223Martijn Coenen                Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
16343fb14d0868594c78a777e805545209636814e223Martijn Coenen                        tag.getTechExtras(), tag.getHandle(), mNfcTagService);
16353fb14d0868594c78a777e805545209636814e223Martijn Coenen                return newTag;
16363fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
16373fb14d0868594c78a777e805545209636814e223Martijn Coenen            return null;
16383fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
16393fb14d0868594c78a777e805545209636814e223Martijn Coenen
16403fb14d0868594c78a777e805545209636814e223Martijn Coenen
16413fb14d0868594c78a777e805545209636814e223Martijn Coenen        @Override
16421b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
16431b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16441b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
16451b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
16461b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16481b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
16491b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void resetIsoDepTimeout() throws RemoteException {
16501b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
16511b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
16521b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.resetIsoDepTimeout();
16531b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
16540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1657f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1658fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1660d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1661f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1668f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1682d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1698f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1699fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1701d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1704f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
17080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1709f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
171949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
17200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1722f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1723fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1725d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1726f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1729f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1734f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
17390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
17410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1743f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1745f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1746fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1748d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1751f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
17550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1756f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
17650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1766f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1767fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1769d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1770f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1773f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1778f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
17830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1784b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
17850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
178649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
17870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1788f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
17890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1790f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1792f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1793fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1795d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1796f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
17990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1802f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1803f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
18080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1814f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1815fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
18160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1817d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1820f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1824f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1825f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
18300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
18320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1833f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1834fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
183597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
183697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1837d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1838f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1840f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
18420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
18430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1844f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1845f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
18470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
18480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
18490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
18500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
18510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
18520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
18530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
18540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
18550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
18560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1857f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
185849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
185949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
186049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
186149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
186249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
186349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
186449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
186549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
186649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
186749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
186849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
186949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1871bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
187249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
187393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1874bd555ee64250126b60b24814120a2049943920caNick Pelly
187549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
187649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
187749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
187849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
187949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
188049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
188249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
188349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
188549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
188649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
188749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
188849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
188949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
189049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
189149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
189249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
189449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
189549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
189649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
189749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1898ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doSetIsoDepTimeout(10000);
1899ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
190049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
190149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
190249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
190349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
190449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
190549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
190649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
19070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1909bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
191049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
191193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
19120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
191349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
191449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
191549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _close();
191649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
191749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
191849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
19190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
192049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
192149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
19220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
192349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        void _close() throws IOException, RemoteException {
192449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            // Blocks until a pending open() or transceive() times out.
192549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            //TODO: This is incorrect behavior - the close should interrupt pending
192649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            // operations. However this is not supported by current hardware.
19270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
192849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
192949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
193049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
1931221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
193249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null) {
193349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE closed");
193449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
193549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe.pid != -1 && getCallingPid() != mOpenEe.pid) {
193649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
1937221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1938221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas
1939ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doResetIsoDepTimeout();
194049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mSecureElement.doDisconnect(mOpenEe.handle);
194149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = null;
194249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
194349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
19440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1947bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
194849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
194993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1950bd555ee64250126b60b24814120a2049943920caNick Pelly
195149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
195249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
195349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
195449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
195549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
195649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
195749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
195849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
196049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
196149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
196349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
196449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
196549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
196649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
196749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
196849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
196949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
197049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
197149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
197249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
197349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
19740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
197649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
19770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1979bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
198049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
198193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
198249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
19830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1985bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
198649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
198793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
198849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
198949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
19900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
1991bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1992bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1993bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void registerTearDownApdus(String packageName, ApduList apdu) throws RemoteException {
1994bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1995a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
1996a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
1997bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1998bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1999bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
2000bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void unregisterTearDownApdus(String packageName) throws RemoteException {
2001bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
2002a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
2003a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
2004bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
20050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
20060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
200749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
200849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
200949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
201049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
201149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
201249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
201349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
201449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
2015bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
201649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
201749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
201849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
201949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
20200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
202149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mExtrasService.close();
202249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) { /* local call never fails */ }
20230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
20240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
20250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
20260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
20270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
20286efda9f3970382554437be037aed863be9889499Sylvain Fonteneau        applyProperties();
20296efda9f3970382554437be037aed863be9889499Sylvain Fonteneau
20300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
20310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
203265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
203349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
203465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
203649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
203757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
203857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
2039ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
204057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
20420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
2043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
2046f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
2048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2049f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
205049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
205149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
205249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
2053275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (mScreenUnlocked) {
205449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
205549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
205649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doSelectSecureElement(SECURE_ELEMENT_ID);
205749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
205849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
205949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
2060221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
206149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
206249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
206349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
206449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
206549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
206649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.disableDiscovery();
2067221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
2068221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
206949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
207049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
207149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
207249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.disableDiscovery();
2073221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
207465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
207565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
207665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20772436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
20782436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
20792436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
20802436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
20812436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
20822436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
2083663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
2084663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
20852436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
20862436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
20872436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
2088663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
2089663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
2090663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
2091663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2092663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
2093663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
2094663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2095663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
2096663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
2097663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
2098663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2099663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
2100663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
21012436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
21022436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
21032436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
21042436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
2105a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
2106a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
2107a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2108a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
2109a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
2110a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2111a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
2112a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
2113a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2114a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
2115bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2116a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
2117a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
2118a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
2119a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            executeSeReset();
2120a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
2121a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
2122a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2123a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
2124bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2125a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
2126a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
2127a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
2128a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
2129a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
2130a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2131a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2132a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
2133a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
2134a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
2135a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
2136a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2137a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2138bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2139a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
2140a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
2141bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2142a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
2143a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
2144bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2145bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2146a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
2147a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
2148a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
2149bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2150bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2151a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
2152a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
2153bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2154a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
2155a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
2156bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2157a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
2158a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
2159bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2160a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
2161bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2162a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
2163a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
2164bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2165bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2166a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
2167a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
2168a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
2169bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2170a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
2171a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
2172bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2173bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2174a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
2175a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
2176bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2177bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2178bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2179bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2180bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2181a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
2182bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2183bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2184f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2185f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2186f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2187f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2188f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2189f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2190f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2191f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2192f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2193f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2194f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2195f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2196f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2197f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2198f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2199f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2200f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
22010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
22020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
22032f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
22040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
22052f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
22064acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
22072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
22084acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
22092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
22102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
22112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
221257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
221357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
221457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
221557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
221657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
221757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
221857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
221957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
222057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
222157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
222357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
222557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
222657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
222757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
222857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
222957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
223057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
223157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
223257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
223357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
223457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
223557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
223657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
223757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
223857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
223957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
224057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
224157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
224257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
224357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
224457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
224557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
224657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
224757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
224857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
224957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
225057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
225157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
225257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
225357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
225457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
225557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
225657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
225757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
225857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
225957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
226057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
22610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
22652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
226674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
226774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22772f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2289b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2290b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2291b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22922f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2293b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2297bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2298bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2299bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2300bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2307d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2308d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2309d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2310d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
23111be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23121be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23131be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23141be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2315d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2316d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2317d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2318d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2319d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2320d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2321d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2322d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2323d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2324d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2325d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2326d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
23271be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23281be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23291be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23301be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2331d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2332d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2333d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2334d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2335d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2336d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2337d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
23390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
23400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
23410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
23440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2346ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
23470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
23480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
235057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2351b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
235257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
235357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2354b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2355b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2356b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2357b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2358b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2359b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2360b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
23613fb14d0868594c78a777e805545209636814e223Martijn Coenen    static public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
23623fb14d0868594c78a777e805545209636814e223Martijn Coenen        // Try to find NDEF on any of the technologies.
23633fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] technologies = nativeTag.getTechList();
23643fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] handles = nativeTag.getHandleList();
23653fb14d0868594c78a777e805545209636814e223Martijn Coenen        int techIndex = 0;
23663fb14d0868594c78a777e805545209636814e223Martijn Coenen        int lastHandleScanned = 0;
23673fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean ndefFoundAndConnected = false;
23683fb14d0868594c78a777e805545209636814e223Martijn Coenen        NdefMessage[] ndefMsgs = null;
23693fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean foundFormattable = false;
23703fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableHandle = 0;
23713fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableLibNfcType = 0;
23723fb14d0868594c78a777e805545209636814e223Martijn Coenen
23733fb14d0868594c78a777e805545209636814e223Martijn Coenen        while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
23743fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (handles[techIndex] != lastHandleScanned) {
23753fb14d0868594c78a777e805545209636814e223Martijn Coenen                // We haven't seen this handle yet, connect and checkndef
23763fb14d0868594c78a777e805545209636814e223Martijn Coenen                if (nativeTag.connect(technologies[techIndex])) {
23773fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Check if this type is NDEF formatable
23783fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (!foundFormattable) {
23793fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (nativeTag.isNdefFormatable()) {
23803fb14d0868594c78a777e805545209636814e223Martijn Coenen                            foundFormattable = true;
23813fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableHandle = nativeTag.getConnectedHandle();
23823fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableLibNfcType = nativeTag.getConnectedLibNfcType();
23833fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // We'll only add formattable tech if no ndef is
23843fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // found - this is because libNFC refuses to format
23853fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // an already NDEF formatted tag.
23863fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
23873fb14d0868594c78a777e805545209636814e223Martijn Coenen                        nativeTag.reconnect();
23883fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, already found formattable technology
23893fb14d0868594c78a777e805545209636814e223Martijn Coenen
23903fb14d0868594c78a777e805545209636814e223Martijn Coenen                    int[] ndefinfo = new int[2];
23913fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (nativeTag.checkNdef(ndefinfo)) {
23923fb14d0868594c78a777e805545209636814e223Martijn Coenen                        ndefFoundAndConnected = true;
23933fb14d0868594c78a777e805545209636814e223Martijn Coenen                        boolean generateEmptyNdef = false;
23943fb14d0868594c78a777e805545209636814e223Martijn Coenen
23953fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int supportedNdefLength = ndefinfo[0];
23963fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int cardState = ndefinfo[1];
23973fb14d0868594c78a777e805545209636814e223Martijn Coenen                        byte[] buff = nativeTag.read();
23983fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (buff != null) {
23993fb14d0868594c78a777e805545209636814e223Martijn Coenen                            ndefMsgs = new NdefMessage[1];
24003fb14d0868594c78a777e805545209636814e223Martijn Coenen                            try {
24013fb14d0868594c78a777e805545209636814e223Martijn Coenen                                ndefMsgs[0] = new NdefMessage(buff);
24023fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.addNdefTechnology(ndefMsgs[0],
24033fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedHandle(),
24043fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedLibNfcType(),
24053fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedTechnology(),
24063fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        supportedNdefLength, cardState);
24073fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.reconnect();
24083fb14d0868594c78a777e805545209636814e223Martijn Coenen                            } catch (FormatException e) {
24093fb14d0868594c78a777e805545209636814e223Martijn Coenen                               // Create an intent anyway, without NDEF messages
24103fb14d0868594c78a777e805545209636814e223Martijn Coenen                               generateEmptyNdef = true;
2411232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
24123fb14d0868594c78a777e805545209636814e223Martijn Coenen                        } else {
24133fb14d0868594c78a777e805545209636814e223Martijn Coenen                            generateEmptyNdef = true;
24143fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
2415232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
24163fb14d0868594c78a777e805545209636814e223Martijn Coenen                       if (generateEmptyNdef) {
24173fb14d0868594c78a777e805545209636814e223Martijn Coenen                           ndefMsgs = new NdefMessage[] { };
24183fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.addNdefTechnology(null,
24193fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedHandle(),
24203fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedLibNfcType(),
24213fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedTechnology(),
24223fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   supportedNdefLength, cardState);
24233fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.reconnect();
24243fb14d0868594c78a777e805545209636814e223Martijn Coenen                       }
24253fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, no NDEF on this tech, continue loop
24263fb14d0868594c78a777e805545209636814e223Martijn Coenen                } else {
24273fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Connect failed, tag maybe lost. Try next handle
24283fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // anyway.
2429232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2430e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
24313fb14d0868594c78a777e805545209636814e223Martijn Coenen            lastHandleScanned = handles[techIndex];
24323fb14d0868594c78a777e805545209636814e223Martijn Coenen            techIndex++;
2433232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
24343fb14d0868594c78a777e805545209636814e223Martijn Coenen        if (ndefMsgs == null && foundFormattable) {
24353fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Tag is not NDEF yet, and found a formattable target,
24363fb14d0868594c78a777e805545209636814e223Martijn Coenen            // so add formattable tech to tech list.
24373fb14d0868594c78a777e805545209636814e223Martijn Coenen            nativeTag.addNdefFormatableTechnology(
24383fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableHandle,
24393fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableLibNfcType);
24403fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
24413fb14d0868594c78a777e805545209636814e223Martijn Coenen
24423fb14d0868594c78a777e805545209636814e223Martijn Coenen        return ndefMsgs;
24433fb14d0868594c78a777e805545209636814e223Martijn Coenen    }
24443fb14d0868594c78a777e805545209636814e223Martijn Coenen
24453fb14d0868594c78a777e805545209636814e223Martijn Coenen
24463fb14d0868594c78a777e805545209636814e223Martijn Coenen    final class NfcServiceHandler extends Handler {
2447232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2448b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2449b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2450f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2451b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2452b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2453b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2454b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2455b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
245657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
245757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
24583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
245957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
246057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
246157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2462f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2463ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2464f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2465232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2466232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2467232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
246898eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2469232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2470232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2471232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2472232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
247398eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
24743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2475232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2476232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2477232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2478f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2479f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2480f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
24813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2482f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2483ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2484f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
248549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
248649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
248749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
248849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
248949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
249093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2491f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2492f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2493f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2494f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2495f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2496f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2497f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2498f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2499ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2500f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2501f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2502f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2503f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2504f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2505ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2506663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2507663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2508eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2509eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2510eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2511eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2512eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2513b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2514b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2515f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2516ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2517f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2518b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2519eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
25207f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
25217f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2522f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2523f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2524f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2525ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2526f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2527f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2528f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2529f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2530ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2531663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2532663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2533eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2534eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
25356f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2536ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2537f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2538b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2539f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2540f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2541f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2542eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2543eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2544eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2545663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2546663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2547663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2548663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2549663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2550663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2551663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2552663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2553663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2554663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2555663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2556663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2557cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2558eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2559f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2560f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2561f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2562f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2563f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2564ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2565f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2566f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2567f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2568f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2569f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2570ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2571f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2572f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2573ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2574f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2575f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2576f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
257757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
257857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
257957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
258057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
258157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
258257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
258357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
258457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
258557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
258657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
258757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
258857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
258957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
259057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2591c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2592c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2593c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
259449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
2595c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
259693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2597c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2598c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2599c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2600c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2601c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2602c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
260349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
2604c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
260593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2606c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2607c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2608c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2609f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2610f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2611f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2612f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2613b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2614d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
26153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
26163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2617b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2618b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2619b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2620b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2621d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2622d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
26233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
26253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
26260c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
262710389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            registerTagObject(nativeTag);
262810389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            if (!dispatchTag(tag, msgs)) {
262910389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen                unregisterObject(nativeTag.getHandle());
26303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
26313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
26353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
26363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
26383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
26403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
26413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
26433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
26443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
26463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
26493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
26503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
26523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
26533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
26543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
26553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
26563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
26573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
26583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
26593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
26603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
26613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
26623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
26653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
26663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
2667adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            try {
2668adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                switch (tnf) {
2669adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_MIME_MEDIA: {
2670adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setType(new String(type, Charsets.US_ASCII));
26713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
2672adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
267321ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
2674adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_ABSOLUTE_URI: {
26755223d6aafa38c8dbbe684f1f8611ee0f46e7ef02Jeff Hamilton                        intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
2676adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return true;
2677adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
267821ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
2679adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_WELL_KNOWN: {
2680adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        byte[] payload = record.getPayload();
2681adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (payload == null || payload.length == 0) return false;
2682adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
2683adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setType("text/plain");
2684adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2685adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
2686adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // Parse the smart poster looking for the URI
2687adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            try {
2688adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                NdefMessage msg = new NdefMessage(record.getPayload());
2689adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                for (NdefRecord subRecord : msg.getRecords()) {
2690adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    short subTnf = subRecord.getTnf();
2691adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    if (subTnf == NdefRecord.TNF_WELL_KNOWN
2692adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                            && Arrays.equals(subRecord.getType(),
2693adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                    NdefRecord.RTD_URI)) {
2694adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(parseWellKnownUriRecord(subRecord));
2695adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2696adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) {
26975223d6aafa38c8dbbe684f1f8611ee0f46e7ef02Jeff Hamilton                                        intent.setData(Uri.parse(new String(subRecord.getType(),
2698adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                Charsets.UTF_8)));
2699adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2700adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    }
27013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
2702adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            } catch (FormatException e) {
2703adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                return false;
27043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
2705adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
2706adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setData(parseWellKnownUriRecord(record));
2707adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
27083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
2709adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return false;
27103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
271121ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
271221ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                    case NdefRecord.TNF_EXTERNAL_TYPE: {
271321ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                        intent.setData(Uri.parse("vnd.android.nfc://ext/" +
271421ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                                new String(record.getType(), Charsets.US_ASCII)));
271521ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                        return true;
271621ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                    }
27173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
2718adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
2719adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            } catch (Exception e) {
2720adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                Log.e(TAG, "failed to parse record", e);
2721adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
27223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
27243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
27263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
27273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
27283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
27293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
27303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
273205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            IntentFilter[] overrideFilters;
273305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            PendingIntent overrideIntent;
273424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] overrideTechLists;
2735a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            boolean foregroundNdefPush = mNdefPushClient.getForegroundMessage() != null;
273605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (mNfcAdapter) {
273705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideFilters = mDispatchOverrideFilters;
273805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideIntent = mDispatchOverrideIntent;
273924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                overrideTechLists = mDispatchOverrideTechLists;
274005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
274105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
274205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // First look for dispatch overrides
2743a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (overrideIntent != null) {
274405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
274549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
274624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters,
274724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideTechLists)) {
274805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        if (DBG) Log.d(TAG, "Dispatched to override");
274905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
275005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
275105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch override registered, but no filters matched");
275205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (CanceledException e) {
275305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
275405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (mNfcAdapter) {
275505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
275605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
275724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mDispatchOverrideTechLists = null;
275805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
275905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
276005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
276105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
2762a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // If there is not foreground NDEF push setup try a normal dispatch.
2763a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            //
2764a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // This is avoided when disabled in the NDEF push case to avoid the situation where each
2765a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // user has a different app in the foreground, causing each to launch itself on the
2766a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // remote device and the apps swapping which is in the foreground on each phone.
2767a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (!foregroundNdefPush) {
2768a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                try {
276924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return dispatchTagInternal(tag, msgs, null, null, null);
2770a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } catch (CanceledException e) {
2771a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.e(TAG, "CanceledException unexpected here", e);
2772a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2773a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
277405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
2775a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2776a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            return false;
277705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
277805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
277924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        /** Returns true if the tech list filter matches the techs on the tag */
278024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        private boolean filterMatch(String[] tagTechs, String[] filterTechs) {
278124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (filterTechs == null || filterTechs.length == 0) return false;
278224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
278324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            for (String tech : filterTechs) {
278424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (Arrays.binarySearch(tagTechs, tech) < 0) {
278524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return false;
278624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
278724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
278824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            return true;
278924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        }
279024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
279105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        // Dispatch to either an override pending intent or a standard startActivity()
279205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
279324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                PendingIntent overrideIntent, IntentFilter[] overrideFilters,
279424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                String[][] overrideTechLists)
279505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                throws CanceledException{
27963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
279724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
279824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
279924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Try the NDEF content specific dispatch
280024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
28023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
28033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
28043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
28053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
28063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
28073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
28083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
2809adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    if (setTypeOrDataFromNdef(intent, record)) {
2810adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        // The record contains filterable data, try to start a matching activity
281124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (startDispatchActivity(intent, overrideIntent, overrideFilters,
281224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                                overrideTechLists)) {
2813adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // If an activity is found then skip further dispatching
2814adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2815adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else {
2816adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
2817adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        }
28183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
28193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
28203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
282224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
282424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
282524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[] tagTechs = tag.getTechList();
282624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            Arrays.sort(tagTechs);
282724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
282824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (overrideIntent != null) {
282924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // There are dispatch overrides in place
283024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideTechLists != null) {
283124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    for (String[] filterTechs : overrideTechLists) {
283224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (filterMatch(tagTechs, filterTechs)) {
283324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            // An override matched, send it to the foreground activity.
283424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            intent = buildTagIntent(tag, msgs,
28358d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                                    NfcAdapter.ACTION_TECH_DISCOVERED);
283624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideIntent.send(mContext, Activity.RESULT_OK, intent);
283724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            return true;
283824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        }
283924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
284024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
284105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
284224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Standard tech dispatch path
284324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
284424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ComponentInfo> registered = mTechListFilters.getComponents();
2845160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen                PackageManager pm = getPackageManager();
284649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
284724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Check each registered activity to see if it matches
284824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                for (ComponentInfo info : registered) {
284924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Don't allow wild card matching
2850160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen                    if (filterMatch(tagTechs, info.techs) &&
2851160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenen                            isComponentEnabled(pm, info.resolveInfo)) {
28523ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        // Add the activity as a match if it's not already in the list
28533ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        if (!matches.contains(info.resolveInfo)) {
28543ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                            matches.add(info.resolveInfo);
28553ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        }
285624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
285724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
285849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
285924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (matches.size() == 1) {
286024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Single match, launch directly
28618d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED);
286224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    ResolveInfo info = matches.get(0);
286324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
286424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
286524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
286624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
286724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
286824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
286924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
287024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (matches.size() > 1) {
287124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Multiple matches, show a custom activity chooser dialog
287224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent = new Intent(mContext, TechListChooserActivity.class);
287324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
287424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putExtra(Intent.EXTRA_INTENT,
28758d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                            buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED));
287624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
287724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            matches);
287824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
287924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
288024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
288124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
288224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
288324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
288424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else {
288524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // No matches, move on
288649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    if (DBG) Log.w(TAG, "No activities for technology handling");
288724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
28883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
289024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
289224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
289424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters, overrideTechLists)) {
28953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
289605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
28973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
28983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
28993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
29003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
290105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
290205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
290324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] overrideFilters, String[][] overrideTechLists)
290424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                throws CanceledException {
290505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideIntent != null) {
2906a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                boolean found = false;
290724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideFilters == null && overrideTechLists == null) {
2908a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // No filters means to always dispatch regardless of match
2909a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    found = true;
291024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (overrideFilters != null) {
2911a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : overrideFilters) {
2912a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
2913a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            found = true;
2914a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            break;
2915a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
291605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
291705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
2918a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2919a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (found) {
2920a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.i(TAG, "Dispatching to override intent " + overrideIntent);
2921a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    overrideIntent.send(mContext, Activity.RESULT_OK, intent);
2922a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return true;
2923a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
2924a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2925a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
292605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
292705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
29281a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // If the current app called stopAppSwitches() then our startActivity()
29291a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // can be delayed for several seconds. This happens with the default home
29301a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // screen. As a system service we can override this behavior with
29311a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // resumeAppSwitches()
29321a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    mIActivityManager.resumeAppSwitches();
29331a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                } catch (RemoteException e) { }
29341a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                try {
293505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    mContext.startActivity(intent);
293605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return true;
293705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (ActivityNotFoundException e) {
293805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return false;
293905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
294005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
294105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
2942b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2943b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2944b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
294549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
29467c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2947fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2948275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        protected Void doInBackground(Boolean... params) {
2949275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]);
2950275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2951275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (params != null && params.length > 0 && params[0]) {
2952161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2953275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (!mScreenUnlocked) {
2954275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = true;
2955275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2956275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2957275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring enable request");
2958275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2959161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
29607c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2961533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2962161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2963275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (mScreenUnlocked) {
2964275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = false;
2965275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2966275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        maybeDisconnectTarget();
2967275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2968275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring disable request");
2969275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2970161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2971533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
29727c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
29737c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
29747c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
29757c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
29767c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
29770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
29780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
29790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2980eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2982ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
29830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
298549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
298765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
29887c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
29897c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
29907c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
29917c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2992275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2993275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Only enable if the screen is unlocked. If the screen is locked
2994275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Intent.ACTION_USER_PRESENT will be broadcast when the screen is
2995275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // unlocked.
2996275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                boolean enable = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
2997275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2998275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(enable);
299965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
30007c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
30017c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
30027c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
30037c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
3004275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.FALSE);
3005275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
3006275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // The user has unlocked the screen. Enabled!
3007275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
3008bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
3009a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
3010bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
30117a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
30127a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
30137a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
30147a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
30157a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
30167a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
30177a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
3018a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                        if (packageName.equals(mSePackageName)) {
3019a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
30207a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
3021bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
3022bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
3023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
3025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
302674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
3027