NfcService.java revision 84e1e0adc2516afd35ebab029a52e764e0490559
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;
3005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
3193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.app.PendingIntent.CanceledException;
32bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.app.StatusBarManager;
33b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
4124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo;
423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
43bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.nfc.ApduList;
44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5049d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
52f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
5924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
609d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
617c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
62b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
63b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6449d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
65b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
66533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
67f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
6813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
69f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
70f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
72bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
7357d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
7457d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
7824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
803ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
8184e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet;
822436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
83bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
843ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
852f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
86bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
87bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
88ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
89fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
91a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
9313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
9413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
9513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
9613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
1003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
1013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
141d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
142fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
145bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
146bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
147bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
148bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
149a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
15093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
151bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
157a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
158a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
160e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
190a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
2010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
2050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
214b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
216b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
217b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
218b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
21957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
22057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
221b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
222c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
223c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
224b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
22649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
22749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
22849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
22949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
23049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
23149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
23249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
23349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
23449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
23549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
23649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
23705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    // Locked on mNfcAdapter
23805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    PendingIntent mDispatchOverrideIntent;
23924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    IntentFilter[] mDispatchOverrideFilters;
24049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    String[][] mDispatchOverrideTechLists;
24105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
24274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
24374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
24574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
24649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
24749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
24849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
24949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
25049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private static final int SECURE_ELEMENT_ID = 11259375;  //TODO: remove hard-coded value
2510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
25249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
25349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
2540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2552f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2562f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2572f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
25865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
25984e1e0adc2516afd35ebab029a52e764e0490559Jason parks    private HashSet<String> mSePackages = new HashSet<String>();
2602f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2612f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
26205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
2630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
266533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
2671a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly    private IActivityManager mIActivityManager;
268ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
269ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
27024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    RegisteredComponentCache mTechListFilters;
271d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
272d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
273d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
27493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
27593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
27693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
27793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
27893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
27993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
28093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
28193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
28293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
28393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
28493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
28593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
28693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
287d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
288d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
289d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2932f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2942f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2952f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
297d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
298d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
300b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
30274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
303ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
304ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
30557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
30624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        mTechListFilters = new RegisteredComponentCache(this,
3078d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
30824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
3090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
3100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
3120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
314d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
316533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
31752028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
318533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
319533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
3201a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly        mIActivityManager = ActivityManagerNative.getDefault();
3211a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly
322d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
324eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
32565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
32665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
327bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
328bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        mContext.registerReceiver(mReceiver, filter);
329bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
330bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
331bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
332bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
333bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
3340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
3350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
3380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
3410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
343a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3573ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3583ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3594acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
360fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
36293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
373fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
37693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
378ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
381aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                isSuccess = _disable(previouslyEnabled);
382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
386fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
38705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
38824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
389a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
39005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
391a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
392a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
393a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
394ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
395ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
396a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
397a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
398a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
399a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
400a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
401a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
402a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
403a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
404a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
405a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
406a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
407a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
408a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
409a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
41024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
41124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
41224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
41324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
41424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
41549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
41605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
417a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent != null) {
41805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "Replacing active dispatch overrides");
41905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
42005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = intent;
421a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = filters;
42224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                mDispatchOverrideTechLists = techLists;
42305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
42405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
42505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
42605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
42705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
42805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
42905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
430a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent == null) {
43105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "No active foreground dispatching");
43205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
43305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = null;
434a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = null;
43505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
43605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
43705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
43805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
439ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
440ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
441ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
442ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
443ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
444ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
445ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
446ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
447ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
448ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
449ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
450ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
451ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
452ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (!mNdefPushClient.setForegroundMessage(null)) {
453ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
454ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
455ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
456ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
457ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
459d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
460bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
4670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
4691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
4701878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
4731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4761878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4791878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4801878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4861878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4871878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4881878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4891878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4901878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4911878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4931878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
497fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
500d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
501bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
5080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
5101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5151878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5171878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
532f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
534fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
537d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
538bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
539f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
540f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
5451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
546bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5471878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5521878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5561878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
5570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
5631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5641878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5651878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5661878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5701878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5711878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
574f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
575fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
577d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
5790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
580bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
581fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
583d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
5850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
586f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
587fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
589d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
5910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
593fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
595d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
5970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
599fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
601d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
605fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
607d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
611bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
61249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
61393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
61449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
6150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
617fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
619d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
6330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
6390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
645f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
648fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
653fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
65593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
6560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
6590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
6620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
6660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
6772f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
6870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
6912f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
7052f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
7192f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
7292f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
7392f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
7492f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
7592f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
7692f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
774f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
776f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
779f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
780d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
781d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
782d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
78357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
78457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
78557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
78657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
78757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
788d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
789d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
790d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
791d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
79293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
79357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
79457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
79557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
79657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
79757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
79857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
79957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
80057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
80157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
80257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
80357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
80457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
80557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
80657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
80757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
80857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
80957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
81057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
81157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
81257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
81357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
81457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
81557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
81657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
81757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
81857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
81957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
82057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
82157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
82257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
82357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
82457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
82557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
82657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
82757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
82857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
82957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
83057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
83157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
83257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
833d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
837f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
838f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
839bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
840bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
841f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
842f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
843bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
844f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
845f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
846fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
848d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
849bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
850f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
851f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
852f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
853f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
854f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
855f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
856f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
857f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
858f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
859f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
8601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
8611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
8621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
8631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
864f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
866f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
867f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
868f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
869fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
871d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
872bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
873f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
875f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
876f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
877f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
878f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
881f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
882f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
88493915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
8850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
8860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
887f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
888f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
889f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
890f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
892f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
894f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
895f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
896fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
898d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
899bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
901f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
902f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
903f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
904f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
906f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
909f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
91193915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
914f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
921f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
923fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
925d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
926bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
928f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
930f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
935f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
940f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
943fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
945d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
946bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
9510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
955f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
9580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
963fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
965d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
966bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
975f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
9780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
9800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
983fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
985d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
9880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
995f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
9980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1007fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1009d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1019f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
10220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
10230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1031fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1033d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1043f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
104528f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
10460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
104728f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
10480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1051fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1053d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1064f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
10680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
10690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
10770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1080f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
1081bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1082bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
1083f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1084f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1085bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
1086f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1087f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1088fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1090d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
10930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
10940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
1101f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
110393915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
11050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
11060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
11072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
11081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
11091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
11101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
11112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
11140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
11150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1120fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1122d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
11290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1132f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11341878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
1135f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1145f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
1146bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1147bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
1148f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1149f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1150bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
1151f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1152f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1153fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1155d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1156bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1165f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
11671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
11681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
11691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1173fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1175d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1176bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1185f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1193fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1195d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1196bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1206f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1218fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1220d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1221bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1231f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1247fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1249d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1250bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1261b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1262b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
126321545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1264b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
126749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1271fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1272ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1273d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1274bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1284b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1285b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1287ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
1288ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1289ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1290ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1291ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1292ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1293ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1294ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1295ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1298fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1299aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1300aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1301aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1302aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1303aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1304aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1305aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1306aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1307aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1308aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1309aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1310aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1311aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1312aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1313aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1314aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1315aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1316aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1317aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1318aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1319aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1320aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1321aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1322b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1323d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1324bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1325f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1331b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1333b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1338fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1357fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1358b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1359b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1360b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1361b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1362b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1363b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1364b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1365b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1366b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1367b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1368b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1369b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1370b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1371b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1372ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1373b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1374b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1375fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
13873ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
13893ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1394fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13959d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
139697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1397d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1398bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14109d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
14119d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
14129d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
14139d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
14149d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
14159d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
14169d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1421fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1423d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1424bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1430f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1435b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1444f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1449fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1451d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1452bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1455f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1456f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1457f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1459f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1466b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1475fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1477bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1480fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
14823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1485fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
148703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
148803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
148903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
149003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
149103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
149203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
149303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
149403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
149503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
149603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
149703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
149803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
149903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
150003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
150103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
150203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
150303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
150403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
150503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
150603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
150703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1509f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15100aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
15110aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
15120aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15130aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15140aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
15150aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15160aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
15170aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
15180aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
15190aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15200aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15210aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
15220aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15230aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
15240aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15250aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15260aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15270aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
15280aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
15290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
15310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
15340aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15351b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
15361b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
15371b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15381b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
15391b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
15401b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15421b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
15431b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void resetIsoDepTimeout() throws RemoteException {
15441b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15451b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
15461b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.resetIsoDepTimeout();
15471b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
15480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1551f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1552fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1554d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
15610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1562f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
15670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
15680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
15690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
15700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1573f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1574fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1576d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1577f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1579f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
15830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
15890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1590f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1591f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1593fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1595d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1596f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1603f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
16080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
161349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
16140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1616f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1617fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1619d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1628f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
16330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
16350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1637f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1640fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1642d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1645f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1650f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
16550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
16560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
16570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
16590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1660f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1661fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1663d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1664f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1667f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1672f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1678b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
16790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
168049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
16810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
16830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1686f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1687fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1689d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1708f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1709fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1711d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1712f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1718f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1719f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
17260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1728fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
172997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
173097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1731d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1732f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1734f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1738f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1739f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
17500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1751f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1752dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
1753dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // Blocks until a pending open() or transceive() times out.
1754dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        //TODO: This is incorrect behavior - the close should interrupt pending
1755dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // operations. However this is not supported by current hardware.
1756dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1757dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        synchronized(NfcService.this) {
1758dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (!mIsNfcEnabled) {
1759dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC adapter is disabled");
1760dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1761dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (mOpenEe == null) {
1762dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC EE closed");
1763dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1764dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
1765dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new SecurityException("Wrong PID");
1766dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1767dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1768dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mManager.doResetIsoDepTimeout();
1769dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mSecureElement.doDisconnect(mOpenEe.handle);
1770dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mOpenEe = null;
1771dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1772dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            applyRouting();
1773dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        }
1774dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    }
1775dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
177649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
177749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
177849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
177949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
178049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
178149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
178249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
178349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
178449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
178549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
178649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
178749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
17880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1789bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
179049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
179193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1792bd555ee64250126b60b24814120a2049943920caNick Pelly
179349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
179449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
179549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
179649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
179749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
179849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
17990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
180049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
180149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
180349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
180449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
180549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
180649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
180749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
180849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
180949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
181049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
181249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
181349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
181449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
181549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1816ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doSetIsoDepTimeout(10000);
1817ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
181849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
181949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
182049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
182149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
182249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
182349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
182484e1e0adc2516afd35ebab029a52e764e0490559Jason parks
182584e1e0adc2516afd35ebab029a52e764e0490559Jason parks                // Add the calling package to the list of packages that have accessed
182684e1e0adc2516afd35ebab029a52e764e0490559Jason parks                // the secure element.
182784e1e0adc2516afd35ebab029a52e764e0490559Jason parks                for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) {
182884e1e0adc2516afd35ebab029a52e764e0490559Jason parks                    mSePackages.add(packageName);
182984e1e0adc2516afd35ebab029a52e764e0490559Jason parks                }
183049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
18310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1833bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
183449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
183593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
18360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
183749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
183849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
1839dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                _nfcEeClose(true, getCallingPid());
184049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
184149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
184249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
184449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
184549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1847bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
184849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
184993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1850bd555ee64250126b60b24814120a2049943920caNick Pelly
185149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
185249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
185349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
185449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
185549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
185649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
185749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
185849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
186049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
186149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
186349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
186449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
186549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
186649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
186749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
186849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
186949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
187049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
187149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
187249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
187349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
187649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
18770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1879bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
188049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
188193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
188249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
18830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1885bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
188649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
188793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
188849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
188949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
18900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
1891bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1892bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1893bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void registerTearDownApdus(String packageName, ApduList apdu) throws RemoteException {
1894bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1895a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
1896a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
1897bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1898bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1899bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1900bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void unregisterTearDownApdus(String packageName) throws RemoteException {
1901bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1902a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
1903a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
1904bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
19050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
19060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
190749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
190849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
190949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
191049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
191149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
191249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
191349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
191449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1915bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
191649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
191749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
191849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
191949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
19200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
1921dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                    _nfcEeClose(false, -1);
1922dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                } catch (IOException e) { /* already closed */ }
19230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
19260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
19286efda9f3970382554437be037aed863be9889499Sylvain Fonteneau        applyProperties();
19296efda9f3970382554437be037aed863be9889499Sylvain Fonteneau
19300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
19310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
193265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
193349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
193465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
19350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
193649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
193757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
1939ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
194057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
1941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
1942aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            Log.w(TAG, "Error enabling NFC");
19430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
1947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1951aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    private boolean _disable(boolean oldEnabledState) {
19522edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        /* sometimes mManager.deinitialize() hangs, watch-dog it */
19532edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        WatchDogThread watchDog = new WatchDogThread();
19542edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        watchDog.start();
19552edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly
1956aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean isSuccess;
1957aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1958aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        /* tear down the my tag server */
1959aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mNdefPushServer.stop();
1960aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1961aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // Stop watchdog if tag present
1962aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // A convenient way to stop the watchdog properly consists of
1963aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // disconnecting the tag. The polling loop shall be stopped before
1964aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // to avoid the tag being discovered again.
1965aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mIsDiscoveryOn = false;
1966aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        applyRouting();
1967aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        maybeDisconnectTarget();
1968aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1969aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        isSuccess = mManager.deinitialize();
1970aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
1971aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (isSuccess) {
1972aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mIsNfcEnabled = false;
1973aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            // Clear out any old dispatch overrides and NDEF push message
1974aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            synchronized (this) {
1975aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                mDispatchOverrideFilters = null;
1976aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                mDispatchOverrideIntent = null;
1977aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1978aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mNdefPushClient.setForegroundMessage(null);
1979aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1980aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1981aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        updateNfcOnSetting(oldEnabledState);
1982aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
19832edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        watchDog.cancel();
1984aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        return isSuccess;
1985aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    }
1986aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
19872edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly    private class WatchDogThread extends Thread {
19882edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        boolean mWatchDogCanceled = false;
19892edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        @Override
19902edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        public void run() {
19912edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            boolean slept = false;
19922edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            while (!slept) {
19932edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                try {
19942edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    Thread.sleep(10000);
19952edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    slept = true;
19962edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                } catch (InterruptedException e) { }
19972edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            }
19982edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            synchronized (this) {
19992edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                if (!mWatchDogCanceled) {
20002edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    // Trigger watch-dog
20012edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    Log.e(TAG, "Watch dog triggered");
20022edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    mManager.doAbort();
20032edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                }
20042edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            }
20052edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        }
20062edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        public synchronized void cancel() {
20072edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            mWatchDogCanceled = true;
20082edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        }
20092edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly    }
20102edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly
201149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
201249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
201349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
201449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            if (mScreenOn) {
201549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
201649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
201749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doSelectSecureElement(SECURE_ELEMENT_ID);
201849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
201949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
202049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
2021221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
202249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
202349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
202449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
202549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
202649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
202749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.disableDiscovery();
2028221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
2029221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
203049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
203149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
203249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
203349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.disableDiscovery();
2034221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
203565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
203665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
203765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20382436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
20392436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
20402436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
20412436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
20422436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
20432436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
2044663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
2045663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
20462436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
20472436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
20482436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
2049663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
2050663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
2051663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
2052663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2053663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
2054663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
2055663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2056663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
2057663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
2058663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
2059663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2060663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
2061663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
20622436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
20632436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
20642436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
20652436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
2066a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
2067a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
2068a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2069a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
2070a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
2071a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2072a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
2073a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
2074a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2075a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
2076bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2077a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
2078a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
2079a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
2080a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
2081a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
20822edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            executeSeReset();
2083a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2084a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
2085bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2086a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
2087a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
2088a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
2089a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
2090a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
2091a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2092a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2093aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2094aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean tempEnable = !mIsNfcEnabled;
2095aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
2096aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (!_enable(false)) {
2097aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                Log.w(TAG, "Could not enable NFC to reset EE!");
2098aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                return;
2099aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
2100aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
2101aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2102a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
2103a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
2104a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
2105a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
2106aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (tempEnable) {
2107aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                _disable(true);
2108aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
2109a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2110a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2111bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2112a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
2113a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
2114bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2115a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
2116a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
2117aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2118aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
2119aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            _disable(true);
2120aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
2121bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2122bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2123a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
2124a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
2125a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
2126bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2127bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2128a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
2129a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
2130bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2131a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
2132a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
2133bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2134a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
2135a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
2136bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2137a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
2138bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2139a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
2140a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
2141bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2142bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2143a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
2144a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
2145a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
2146bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2147a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
2148a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
2149bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2150bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2151a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
2152a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
2153bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2154bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2155bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2156bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2157bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2158a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
2159bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2160bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2161f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2162f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2163f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2164f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2165f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2166f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2167f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2168f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2169f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2170f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2171f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2172f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2173f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2174f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2175f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2176f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2177f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
21790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
21802f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
21810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
21822f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
21834acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
21842f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
21854acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
21862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
21872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
21882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
218957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
219157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
219357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
219557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
219657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
219757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
219857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
220057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
220157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
220257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
220357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
220457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
220557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
220657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
220757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
220857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
220957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
221057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
221157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
221257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
221357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
221457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
221557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
221657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
221757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
221857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
221957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
222057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
222157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
222257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
222357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
222457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
222557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
222657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
222757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
222857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
222957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
223057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
223157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
223257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
223357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
223457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
223557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
223657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
223757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
22380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
22422f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
224374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
224474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2266b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2267b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2268b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2270b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22732f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2274bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2275bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2276bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2277bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2284d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2285d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2286d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2287d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
22881be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22891be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22901be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22911be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2292d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2293d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2294d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2295d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2296d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2297d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2298d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2299d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2300d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2301d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2302d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2303d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
23041be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
23051be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
23061be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
23071be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2308d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2309d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2310d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2311d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2313d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2314d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
23160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
23170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
23180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
23200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
23210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2323ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
23240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
23250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
232757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2328b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
232957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
233057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2331b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2332b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2333b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2334b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2335b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2336b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2337b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2338b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2339232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2340232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
2341232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            // Try to find NDEF on any of the technologies.
2342232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] technologies = nativeTag.getTechList();
2343232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] handles = nativeTag.getHandleList();
2344232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int techIndex = 0;
2345232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int lastHandleScanned = 0;
2346232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            boolean ndefFoundAndConnected = false;
2347232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            NdefMessage[] ndefMsgs = null;
2348eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen            boolean foundFormattable = false;
2349e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableHandle = 0;
2350e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableTechnology = 0;
2351232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2352232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
2353232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                if (handles[techIndex] != lastHandleScanned) {
2354232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    // We haven't seen this handle yet, connect and checkndef
2355232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    if (nativeTag.connect(technologies[techIndex])) {
2356eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        // Check if this type is NDEF formatable
2357434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        if (!foundFormattable) {
2358434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            if (nativeTag.isNdefFormatable()) {
2359434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                foundFormattable = true;
2360434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableHandle = nativeTag.getConnectedHandle();
2361434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableTechnology = nativeTag.getConnectedTechnology();
2362434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // We'll only add formattable tech if no ndef is
2363434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // found - this is because libNFC refuses to format
2364434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // an already NDEF formatted tag.
2365434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            }
2366434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            nativeTag.reconnect();
2367434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        } // else, already found formattable technology
2368434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen
2369232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        int[] ndefinfo = new int[2];
2370232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        if (nativeTag.checkNdef(ndefinfo)) {
2371232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            ndefFoundAndConnected = true;
2372232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            boolean generateEmptyNdef = false;
2373232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2374232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int supportedNdefLength = ndefinfo[0];
2375232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int cardState = ndefinfo[1];
2376232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            byte[] buff = nativeTag.read();
2377232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            if (buff != null) {
2378232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                ndefMsgs = new NdefMessage[1];
2379232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                try {
2380232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    ndefMsgs[0] = new NdefMessage(buff);
2381232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.addNdefTechnology(ndefMsgs[0],
2382ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                            nativeTag.getConnectedHandle(),
23830a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                            nativeTag.getConnectedLibNfcType(),
2384f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                            nativeTag.getConnectedTechnology(),
2385232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                            supportedNdefLength, cardState);
2386232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.reconnect();
2387232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                } catch (FormatException e) {
2388232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   // Create an intent anyway, without NDEF messages
2389232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   generateEmptyNdef = true;
2390232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                }
2391232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            } else {
2392232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                generateEmptyNdef = true;
2393232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
2394232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2395232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           if (generateEmptyNdef) {
2396232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               ndefMsgs = new NdefMessage[] { };
2397ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                               nativeTag.addNdefTechnology(null,
2398ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       nativeTag.getConnectedHandle(),
23990a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                       nativeTag.getConnectedLibNfcType(),
2400f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                       nativeTag.getConnectedTechnology(),
2401ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       supportedNdefLength, cardState);
2402232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               nativeTag.reconnect();
2403232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           }
2404232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        } // else, no NDEF on this tech, continue loop
2405232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    } else {
2406232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // Connect failed, tag maybe lost. Try next handle
2407232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // anyway.
2408232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    }
2409232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2410232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                lastHandleScanned = handles[techIndex];
2411232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                techIndex++;
2412232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            }
2413e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            if (ndefMsgs == null && foundFormattable) {
2414e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // Tag is not NDEF yet, and found a formattable target,
2415e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // so add formattable tech to tech list.
2416e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                nativeTag.addNdefFormatableTechnology(
2417e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableHandle,
2418e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableTechnology);
2419e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
2420232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2421232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            return ndefMsgs;
2422232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
2423232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2424b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2425b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2426f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2427b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2428b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2429b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2430b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2431b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
243257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
243357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
24343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
243557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
243657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
243757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2438f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2439ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2440f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2441232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2442232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2443232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
244498eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2445232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2446232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2447232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2448232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
244998eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
24503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2451232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2452232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2453232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2454f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2455f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2456f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
24573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2458f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2459ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2460f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
246149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
246249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
246349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
246449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
246549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
246693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2467f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2468f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2469f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2470f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2471f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2472f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2473f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2474f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2475ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2476f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2477f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2478f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2479f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2480f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2481ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2482663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2483663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2484eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2485eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2486eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2487eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2488eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2489b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2490b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2491f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2492ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2493f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2494b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2495eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
24967f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
24977f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2498f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2499f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2500f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2501ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2502f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2503f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2504f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2505f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2506ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2507663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2508663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2509eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2510eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
25116f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2512ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2513f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2514b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2515f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2516f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2517f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2518eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2519eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2520eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2521663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2522663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2523663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2524663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2525663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2526663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2527663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2528663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2529663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2530663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2531663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2532663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2533cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2534eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2535f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2536f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2537f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2538f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2539f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2540ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2541f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2542f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2543f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2544f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2545f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2546ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2547f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2548f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2549ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2550f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2551f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2552f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
255357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
255457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
255557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
255657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
255757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
255857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
255957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
256057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
256157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
256257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
256357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
256457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
256557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
256657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2567c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2568c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2569c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
257049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
2571c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
257293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2573c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2574c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2575c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2576c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2577c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2578c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
257949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
2580c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
258193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2582c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2583c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2584c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2585f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2586f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2587f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2588f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2589b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2590d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
25913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
25923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2593b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2594b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2595b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2596b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2597d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2598d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
25993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
26013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
26020c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
260310389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            registerTagObject(nativeTag);
260410389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            if (!dispatchTag(tag, msgs)) {
260510389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen                unregisterObject(nativeTag.getHandle());
26063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
26073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
26113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
26123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
26143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
26163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
26173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
26183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
26193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
26203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
26223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
26253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
26263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
26283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
26293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
26303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
26313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
26323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
26333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
26343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
26353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
26363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
26373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
26383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
26413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
26423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
2643adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            try {
2644adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                switch (tnf) {
2645adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_MIME_MEDIA: {
2646adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setType(new String(type, Charsets.US_ASCII));
26473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
2648adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
264921ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
2650adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_ABSOLUTE_URI: {
26515223d6aafa38c8dbbe684f1f8611ee0f46e7ef02Jeff Hamilton                        intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
2652adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return true;
2653adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
265421ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
2655adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_WELL_KNOWN: {
2656adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        byte[] payload = record.getPayload();
2657adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (payload == null || payload.length == 0) return false;
2658adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
2659adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setType("text/plain");
2660adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2661adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
2662adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // Parse the smart poster looking for the URI
2663adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            try {
2664adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                NdefMessage msg = new NdefMessage(record.getPayload());
2665adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                for (NdefRecord subRecord : msg.getRecords()) {
2666adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    short subTnf = subRecord.getTnf();
2667adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    if (subTnf == NdefRecord.TNF_WELL_KNOWN
2668adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                            && Arrays.equals(subRecord.getType(),
2669adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                    NdefRecord.RTD_URI)) {
2670adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(parseWellKnownUriRecord(subRecord));
2671adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2672adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) {
26735223d6aafa38c8dbbe684f1f8611ee0f46e7ef02Jeff Hamilton                                        intent.setData(Uri.parse(new String(subRecord.getType(),
2674adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                Charsets.UTF_8)));
2675adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2676adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    }
26773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
2678adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            } catch (FormatException e) {
2679adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                return false;
26803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
2681adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
2682adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setData(parseWellKnownUriRecord(record));
2683adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
26843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
2685adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return false;
26863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
268721ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton
268821ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                    case NdefRecord.TNF_EXTERNAL_TYPE: {
268921ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                        intent.setData(Uri.parse("vnd.android.nfc://ext/" +
269021ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                                new String(record.getType(), Charsets.US_ASCII)));
269121ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                        return true;
269221ee4b2e782188cbc8e8b7752dd992844a904615Jeff Hamilton                    }
26933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
2694adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
2695adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            } catch (Exception e) {
2696adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                Log.e(TAG, "failed to parse record", e);
2697adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
26983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
27003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
27023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
27033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
27043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
27053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
27063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
270805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            IntentFilter[] overrideFilters;
270905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            PendingIntent overrideIntent;
271024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] overrideTechLists;
2711a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            boolean foregroundNdefPush = mNdefPushClient.getForegroundMessage() != null;
271205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (mNfcAdapter) {
271305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideFilters = mDispatchOverrideFilters;
271405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideIntent = mDispatchOverrideIntent;
271524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                overrideTechLists = mDispatchOverrideTechLists;
271605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
271705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
271805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // First look for dispatch overrides
2719a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (overrideIntent != null) {
272005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
272149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
272224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters,
272324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideTechLists)) {
272405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        if (DBG) Log.d(TAG, "Dispatched to override");
272505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
272605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
272705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch override registered, but no filters matched");
272805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (CanceledException e) {
272905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
273005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (mNfcAdapter) {
273105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
273205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
273324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mDispatchOverrideTechLists = null;
273405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
273505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
273605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
273705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
2738a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // If there is not foreground NDEF push setup try a normal dispatch.
2739a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            //
2740a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // This is avoided when disabled in the NDEF push case to avoid the situation where each
2741a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // user has a different app in the foreground, causing each to launch itself on the
2742a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // remote device and the apps swapping which is in the foreground on each phone.
2743a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (!foregroundNdefPush) {
2744a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                try {
274524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return dispatchTagInternal(tag, msgs, null, null, null);
2746a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } catch (CanceledException e) {
2747a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.e(TAG, "CanceledException unexpected here", e);
2748a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2749a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
275005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
2751a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2752a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            return false;
275305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
275405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
275524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        /** Returns true if the tech list filter matches the techs on the tag */
275624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        private boolean filterMatch(String[] tagTechs, String[] filterTechs) {
275724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (filterTechs == null || filterTechs.length == 0) return false;
275824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
275924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            for (String tech : filterTechs) {
276024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (Arrays.binarySearch(tagTechs, tech) < 0) {
276124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return false;
276224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
276324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
276424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            return true;
276524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        }
276624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
276705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        // Dispatch to either an override pending intent or a standard startActivity()
276805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
276924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                PendingIntent overrideIntent, IntentFilter[] overrideFilters,
277024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                String[][] overrideTechLists)
277105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                throws CanceledException{
27723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
277324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
277424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
277524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Try the NDEF content specific dispatch
277624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
27783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
27793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
27803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
27813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
27823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
27833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
2785adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    if (setTypeOrDataFromNdef(intent, record)) {
2786adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        // The record contains filterable data, try to start a matching activity
278724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (startDispatchActivity(intent, overrideIntent, overrideFilters,
278824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                                overrideTechLists)) {
2789adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // If an activity is found then skip further dispatching
2790adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2791adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else {
2792adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
2793adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        }
27943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
27953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
27963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
279824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
280024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
280124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[] tagTechs = tag.getTechList();
280224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            Arrays.sort(tagTechs);
280324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
280424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (overrideIntent != null) {
280524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // There are dispatch overrides in place
280624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideTechLists != null) {
280724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    for (String[] filterTechs : overrideTechLists) {
280824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (filterMatch(tagTechs, filterTechs)) {
280924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            // An override matched, send it to the foreground activity.
281024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            intent = buildTagIntent(tag, msgs,
28118d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                                    NfcAdapter.ACTION_TECH_DISCOVERED);
281224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideIntent.send(mContext, Activity.RESULT_OK, intent);
281324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            return true;
281424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        }
281524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
281624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
281705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
281824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Standard tech dispatch path
281924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
282024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ComponentInfo> registered = mTechListFilters.getComponents();
282149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
282224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Check each registered activity to see if it matches
282324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                for (ComponentInfo info : registered) {
282424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Don't allow wild card matching
282524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (filterMatch(tagTechs, info.techs)) {
28263ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        // Add the activity as a match if it's not already in the list
28273ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        if (!matches.contains(info.resolveInfo)) {
28283ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                            matches.add(info.resolveInfo);
28293ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        }
283024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
283124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
283249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
283324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (matches.size() == 1) {
283424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Single match, launch directly
28358d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED);
283624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    ResolveInfo info = matches.get(0);
283724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
283824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
283924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
284024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
284124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
284224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
284324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
284424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (matches.size() > 1) {
284524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Multiple matches, show a custom activity chooser dialog
284624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent = new Intent(mContext, TechListChooserActivity.class);
284724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
284824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putExtra(Intent.EXTRA_INTENT,
28498d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                            buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED));
285024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
285124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            matches);
285224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
285324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
285424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
285524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
285624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
285724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
285824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else {
285924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // No matches, move on
286049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    if (DBG) Log.w(TAG, "No activities for technology handling");
286124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
28623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
286424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
286624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
286824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters, overrideTechLists)) {
28693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
287005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
28713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
28723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
28733fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
287505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
287605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
287724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] overrideFilters, String[][] overrideTechLists)
287824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                throws CanceledException {
287905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideIntent != null) {
2880a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                boolean found = false;
288124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideFilters == null && overrideTechLists == null) {
2882a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // No filters means to always dispatch regardless of match
2883a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    found = true;
288424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (overrideFilters != null) {
2885a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : overrideFilters) {
2886a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
2887a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            found = true;
2888a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            break;
2889a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
289005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
289105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
2892a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2893a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (found) {
2894a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.i(TAG, "Dispatching to override intent " + overrideIntent);
2895a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    overrideIntent.send(mContext, Activity.RESULT_OK, intent);
2896a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return true;
2897a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
2898a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2899a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
290005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
290105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
29021a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // If the current app called stopAppSwitches() then our startActivity()
29031a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // can be delayed for several seconds. This happens with the default home
29041a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // screen. As a system service we can override this behavior with
29051a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // resumeAppSwitches()
29061a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    mIActivityManager.resumeAppSwitches();
29071a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                } catch (RemoteException e) { }
29081a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                try {
290905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    mContext.startActivity(intent);
291005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return true;
291105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (ActivityNotFoundException e) {
291205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return false;
291305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
291405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
291505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
2916b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2917b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2918b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
291949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
29207c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2921fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
29227c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
2923df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
2924161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2925161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
292649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
2927161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
29287c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2929161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
29302edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    mWakeLock.acquire();
2931161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
293249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
29332436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    maybeDisconnectTarget();
29342edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    mWakeLock.release();
2935161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
29367c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
29377c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
29387c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
29397c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
29407c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
29410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
29420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
29430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2944eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2946ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
29470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
294949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
295165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
29527c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
29537c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
29547c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
29557c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2956df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(true));
295765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
29587c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
29597c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
29607c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
29617c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2962df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
2963bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2964a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
2965bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
29667a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
29677a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
29687a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
29697a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
29707a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
29717a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
29727a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
297384e1e0adc2516afd35ebab029a52e764e0490559Jason parks                        if (mSePackages.contains(packageName)) {
2974a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
297584e1e0adc2516afd35ebab029a52e764e0490559Jason parks                            mSePackages.remove(packageName);
29767a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
2977bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2978bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
298274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2983