NfcService.java revision 2094515fca0cfa0ac87e9cc260d3953d416afe3e
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;
492094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5149d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
52f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
58f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
6024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
619d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
627c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
63b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
64b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6549d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
66b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
67533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
68f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
6913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
70f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
71f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
73bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
74bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataOutputStream;
7557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
7857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
8024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
823ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
832436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
84bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
853ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
87bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
88bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
89ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
90fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
92bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String TEAR_DOWN_SCRIPTS_FILE_NAME = "teardowns";
9357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
9413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
9513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
9613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
9713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    /**
993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * NFC Forum "URI Record Type Definition"
1003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     *
1013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
1023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
1033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton     */
1043fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    private static final String[] URI_PREFIX_MAP = new String[] {
1053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "", // 0x00
1063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://www.", // 0x01
1073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://www.", // 0x02
1083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "http://", // 0x03
1093fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "https://", // 0x04
1103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tel:", // 0x05
1113fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "mailto:", // 0x06
1123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://anonymous:anonymous@", // 0x07
1133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://ftp.", // 0x08
1143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftps://", // 0x09
1153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sftp://", // 0x0A
1163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "smb://", // 0x0B
1173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "nfs://", // 0x0C
1183fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "ftp://", // 0x0D
1193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "dav://", // 0x0E
1203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "news:", // 0x0F
1213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "telnet://", // 0x10
1223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "imap:", // 0x11
1233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "rtsp://", // 0x12
1243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:", // 0x13
1253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "pop:", // 0x14
1263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sip:", // 0x15
1273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "sips:", // 0x16
1283fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tftp:", // 0x17
1293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btspp://", // 0x18
1303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btl2cap://", // 0x19
1313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "btgoep://", // 0x1A
1323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "tcpobex://", // 0x1B
1333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "irdaobex://", // 0x1C
1343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "file://", // 0x1D
1353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:id:", // 0x1E
1363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:tag:", // 0x1F
1373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:pat:", // 0x20
1383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:raw:", // 0x21
1393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            "urn:epc:", // 0x22
1403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton    };
1413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
142d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
143fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String TAG = "NfcService";
145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
146bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
147bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
148bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
149bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
15093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    // STOPSHIP: This needs to be updated to the line below
15193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton//    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
15293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM = NFC_PERM;
15393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
154bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF = "NfcServicePrefs";
156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
161e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
191a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
2000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
2060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
2080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
2100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
2120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
215b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
216b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
217b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
218b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
219b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
22057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
22157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
222b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
223c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
224c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
225b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
22749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
22849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
22949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
23049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
23149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
23249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
23349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
23449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
23549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
23649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
23749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
23805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    // Locked on mNfcAdapter
23905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    PendingIntent mDispatchOverrideIntent;
24024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton    IntentFilter[] mDispatchOverrideFilters;
24149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    String[][] mDispatchOverrideTechLists;
24205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
24374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
24474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
24674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
24749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
24849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
24949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
25049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
25149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private static final int SECURE_ELEMENT_ID = 11259375;  //TODO: remove hard-coded value
2520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
25349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
25449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
2550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2562f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2572f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2582f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
25965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    private boolean mScreenOn;
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
274bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private HashMap<String, ApduList> mTearDownApdus = new HashMap<String, ApduList>();
275bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
27693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
27793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
27893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
27993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
28093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
28193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
28293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
28393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
28493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
28593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
28693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
28793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
28893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
289d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
290d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
291d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2952f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2972f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
299d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
300d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
302b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mManager = new NativeNfcManager(mContext, this);
3030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
30474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
305ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
306ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
30757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
30824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        mTechListFilters = new RegisteredComponentCache(this,
3098d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
31024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
3110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
3120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
3130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
3140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
316d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
318533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
31952028e699e43e6322021098bbefd761fe6596747Nick Pelly        mScreenOn = pm.isScreenOn();
320533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
321533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
3221a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly        mIActivityManager = ActivityManagerNative.getDefault();
3231a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly
324bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        readTearDownApdus();
325bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
326d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
328eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
32965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
33065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
331bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
332bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        mContext.registerReceiver(mReceiver, filter);
333bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
334bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
335bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
336bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
337bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
3380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.registerReceiver(mReceiver, filter);
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
3410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
3420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
3450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3552f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3603ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3613ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3624acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
363fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
36593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
376fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
37993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
381ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
3846f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                /* tear down the my tag server */
385ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                mNdefPushServer.stop();
386e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
387e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // Stop watchdog if tag present
388e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // A convenient way to stop the watchdog properly consists of
389e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // disconnecting the tag. The polling loop shall be stopped before
390e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                // to avoid the tag being discovered again.
39149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mIsDiscoveryOn = false;
39249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
393e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir                maybeDisconnectTarget();
394e260fc52ed2b4e6e1b7394d6f841d01c98888327Arnaud Ferir
3950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = mManager.deinitialize();
396ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
3980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    mIsNfcEnabled = false;
399a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // Clear out any old dispatch overrides and NDEF push message
40005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (this) {
40105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
40205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
40305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
404a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    mNdefPushClient.setForegroundMessage(null);
4050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
4070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            updateNfcOnSetting(previouslyEnabled);
4090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
413fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
41405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
41524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
416a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
41705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
418a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
419a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
420a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
421ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
422ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
423a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
424a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
425a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
426a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
427a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
428a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
429a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
430a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
431a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
432a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
433a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
434a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
435a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
436a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
43724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
43824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
43924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
44024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
44124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
44249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
44305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
444a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent != null) {
44505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "Replacing active dispatch overrides");
44605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
44705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = intent;
448a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = filters;
44924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                mDispatchOverrideTechLists = techLists;
45005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
45105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
45205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
45305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
45405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
45505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
45605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (this) {
457a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (mDispatchOverrideIntent == null) {
45805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.e(TAG, "No active foreground dispatching");
45905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
46005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                mDispatchOverrideIntent = null;
461a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                mDispatchOverrideFilters = null;
46205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
46305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
46405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
46505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
466ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
467ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
468ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
469ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
470ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
471ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
472ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
473ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
474ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
475ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
476ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4772094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
4782094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
4792094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4802094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
4812094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
4822094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
4832094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (mNdefPushClient.setForegroundCallback(callback)) {
4842094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
4852094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
4862094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
4872094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
4882094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
489ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
490ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4912094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadMsg = mNdefPushClient.setForegroundMessage(null);
4922094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadCallback = mNdefPushClient.setForegroundCallback(null);
4932094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
494ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
495ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
496ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
497ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
498ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) 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
5070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
5080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
5101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
5111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
512f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
5141878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5151878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5171878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
522f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5331878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5341878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
535f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
538fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
5400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
541d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
542bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
544f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
545f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
5490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
5511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5521878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5561878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5571878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5581878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
559f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
560f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
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 int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
578d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
579bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
581f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
5861878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
587bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5881878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
589f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5901878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5911878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5931878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5951878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5961878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
5980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
599f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6001878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
6011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
6021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
6041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6051878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
6061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
6071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
6081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
6091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
6101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
6111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
6121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
613f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
615f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
616fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
618d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
621bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
622fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
624d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
627f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
628fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
630d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
633f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
634fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
636d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
640fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
642d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
646fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
648d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
652bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
65349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
65493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
65549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
6560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
658fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
660d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
6760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
6820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
686f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
687f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
688f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
689fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
694fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
69693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
7060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
7100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
7182f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
7322f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
7462f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
7500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
7602f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
7702f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
7802f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
7840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
7902f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
7940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
8002f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
8102f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
815f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
817f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
820f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
821d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
822d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
823d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
82457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
82557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
82657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
82757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
82857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
829d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
830d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
831d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
832d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
83393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
83457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
83557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
83657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
83757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
83857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
83957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
84057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
84157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
84257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
84357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
84457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
84557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
84657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
84757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
84857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
84957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
85057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
85157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
85257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
85357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
85457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
85557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
85657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
85757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
85857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
85957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
86057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
86157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
86257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
86357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
86457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
86557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
86657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
86757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
86857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
86957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
87057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
87157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
87257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
87357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
874d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
8750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
878f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
879f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
880bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
881bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
882f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
883f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
884bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
885f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
886f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
887fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
889d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
890bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
892f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
893f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
894f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
895f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
896f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
897f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
898f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
899f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
9021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
9031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
9041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
909f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
910fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
912d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
913bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
914f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
921f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
923f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
924f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
92593915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
9260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
9270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
928f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
930f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
937fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
939d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
940bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
950f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
95293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
9610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
964fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
966d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
967bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
9750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
976f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
9800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
984fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
986d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
987bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
9920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
996f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1004fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
1006d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1007bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
10080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1016f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
10190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
10210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1024fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
1026d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1036f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
10390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
10400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1048fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
1050d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1060f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
10630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
10640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
10690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1072fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
1074d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1084f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
108628f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
10870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
108828f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1092fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1094d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1105f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
11080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
11090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
11100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
11140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
11150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
11180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
11200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1121f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
1122bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1123bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
1124f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1125f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1126bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
1127f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1128f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1129fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1131d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
11350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
11390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
1142f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
11430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
114493915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
11450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
11460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
11470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
11482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
11491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
11501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
11511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
11522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
11530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
11540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
11550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
11560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
11570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
11580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
11600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1161fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1163d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
11640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
11660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
11680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
11690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
11700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
11720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1173f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
11740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
11751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
1176f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
11770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
11780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
11790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
11800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
11810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1186f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
1187bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1188bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
1189f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1190f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1191bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
1192f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1193f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1194fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1196d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1197bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1206f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
12081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
12091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
12101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1214fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1216d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1217bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1226f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1234fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1236d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1237bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1247f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1256f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1259fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1261d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1262bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1272f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1288fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1290d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1291bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1293f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1302b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1303b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
130421545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1305b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
130849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1312fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1313ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1314d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1315bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1325b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1326b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1328ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
1329ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1330ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1331ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1332ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1333ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1334ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1335ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1336ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1339fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1340aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1341aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1342aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1343aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1344aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1345aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1346aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1347aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1348aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1349aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1350aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1351aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1352aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1353aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1354aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1355aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1356aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1357aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1358aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1359aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1360aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1361aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1362aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1363b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1364d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1365bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1367f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1372b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1374b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1379fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1398fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1399b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1400b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1401b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1402b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1403b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1404b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1405b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1406b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1407b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1408b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1409b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1410b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1411b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1412b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1413ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1414b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1415b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1416fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
14283ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14303ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1435fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14369d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
143797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1438d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1439bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1444f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1449f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1450f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
14519d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
14529d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
14539d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
14549d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
14559d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
14569d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
14579d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1459f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1462fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1464d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1465bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1467f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1476b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1477f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1478f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1485f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1486f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1487f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1490fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1492d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1493bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1495f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1501f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1507b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1509f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1510f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1511f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1512f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1514f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1516fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1518bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1521fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
15233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1526fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
152803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
152903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
153003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
153103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
153203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
153303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
153403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
153503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
153603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
153703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
153803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
153903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
154003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
154103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
154203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
154303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
154403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
154503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
154603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
154703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
154803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15510aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
15520aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
15530aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15540aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15550aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
15560aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
15580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
15590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
15600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15610aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
15630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
15650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15670aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15680aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
15690aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
15700aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15710aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
15720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
15730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
15740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
15750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
15761b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
15771b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
15781b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15791b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
15801b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
15811b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15831b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
15841b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void resetIsoDepTimeout() throws RemoteException {
15851b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15861b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
15871b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.resetIsoDepTimeout();
15881b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
15890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1590f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1593fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(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.getGeneralBytes();
16080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1615fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1617d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1618f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1631f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1632f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1633f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1634fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1636d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1637f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1644f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
16490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
165449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
16550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1657f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1658fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1660d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1661f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1664f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
16760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1678f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1680f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1681fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1683d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1686f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
16960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
16970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
17000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1701f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1702fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1704d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1708f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1719b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
17200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
172149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
17220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1723f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
17240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1725f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1728fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1730d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
17340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1737f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1738f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1750fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1752d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1753f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1755f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1759f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1760f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
17670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1768f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1769fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
177097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
177197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1772d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1773f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1775f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1779f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1780f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
17850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
17910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1792f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
179349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
179449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
179549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
179649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
179749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
179849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
179949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
180049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
180149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
180249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
180349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
180449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1806bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
180749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
180893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1809bd555ee64250126b60b24814120a2049943920caNick Pelly
181049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
181149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
181249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
181349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
181449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
181549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
181749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
181849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
182049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
182149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
182249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
182349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
182449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
182549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
182649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
182749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
182949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
183049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
183149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
183249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1833ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doSetIsoDepTimeout(10000);
1834ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
183549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
183649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
183749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
183849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
183949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
184049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
184149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
18420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1844bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
184549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
184693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
18470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
184849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
184949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
185049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _close();
185149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
185249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
185349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
185549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
185649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
185849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        void _close() throws IOException, RemoteException {
185949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            // Blocks until a pending open() or transceive() times out.
186049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            //TODO: This is incorrect behavior - the close should interrupt pending
186149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            // operations. However this is not supported by current hardware.
18620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
186349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
186449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
186549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
1866221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
186749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null) {
186849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE closed");
186949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
187049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe.pid != -1 && getCallingPid() != mOpenEe.pid) {
187149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
1872221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1873221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas
1874ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doResetIsoDepTimeout();
187549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mSecureElement.doDisconnect(mOpenEe.handle);
187649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = null;
187749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
187849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
18790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1882bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
188349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
188493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1885bd555ee64250126b60b24814120a2049943920caNick Pelly
188649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
188749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
188849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
188949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
189049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
189149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
189249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
189349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
189549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
189649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
189849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
189949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
190049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
190149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
190249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
190349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
190449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
190549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
190649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
190749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
190849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
19090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
191149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
19120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1914bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
191549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
191693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
191749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
19180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1920bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
192149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
192293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
192349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
192449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
19250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
1926bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1927bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1928bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void registerTearDownApdus(String packageName, ApduList apdu) throws RemoteException {
1929bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1930bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            synchronized(NfcService.this) {
1931bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                mTearDownApdus.put(packageName, apdu);
1932bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                writeTearDownApdusLocked();
1933bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1934bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1935bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1936bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1937bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void unregisterTearDownApdus(String packageName) throws RemoteException {
1938bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1939bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            synchronized(NfcService.this) {
1940bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                mTearDownApdus.remove(packageName);
1941bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                writeTearDownApdusLocked();
1942bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1943bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
19440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
19450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
194649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
194749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
194849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
194949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
195049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
195149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
195249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
195349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1954bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
195549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
195649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
195749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
195849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
19590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
196049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mExtrasService.close();
196149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) { /* local call never fails */ }
19620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
19650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
19676efda9f3970382554437be037aed863be9889499Sylvain Fonteneau        applyProperties();
19686efda9f3970382554437be037aed863be9889499Sylvain Fonteneau
19690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
19700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
197165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
197249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
197365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
19740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
197549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
197657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
197757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
1978ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
197957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
1980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
19810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
1985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
198949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
199049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
199149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
199249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            if (mScreenOn) {
199349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
199449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
199549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doSelectSecureElement(SECURE_ELEMENT_ID);
199649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
199749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
199849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
1999221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
200049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
200149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
200249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
200349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
200449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
200549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.disableDiscovery();
2006221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
2007221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
200849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
200949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
201049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
201149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.disableDiscovery();
2012221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
201365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
201465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
201565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20162436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
20172436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
20182436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
20192436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
20202436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
20212436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
2022663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
2023663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
20242436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
20252436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
20262436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
2027663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
2028663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
2029663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
2030663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2031663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
2032663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
2033663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2034663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
2035663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
2036663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
2037663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2038663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
2039663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
20402436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
20412436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
20422436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
20432436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
2044bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private void readTearDownApdus() {
2045bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        FileInputStream input = null;
2046bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2047bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2048bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            input = openFileInput(TEAR_DOWN_SCRIPTS_FILE_NAME);
2049bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            DataInputStream stream = new DataInputStream(input);
2050bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2051bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            int packagesSize = stream.readInt();
2052bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2053bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            for (int i = 0 ; i < packagesSize ; i++) {
2054bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                String packageName = stream.readUTF();
2055bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                ApduList apdu = new ApduList();
2056bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2057bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                int commandsSize = stream.readInt();
2058bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2059bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                for (int j = 0 ; j < commandsSize ; j++) {
2060bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    int length = stream.readInt();
2061bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2062bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    byte[] cmd = new byte[length];
2063bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2064bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    stream.read(cmd);
2065bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    apdu.add(cmd);
2066bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2067bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2068bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                mTearDownApdus.put(packageName, apdu);
2069bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2070bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (FileNotFoundException e) {
2071bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            // Ignore.
2072bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2073bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            Log.e(TAG, "Could not read tear down scripts file: ", e);
2074bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            deleteFile(TEAR_DOWN_SCRIPTS_FILE_NAME);
2075bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2076bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2077bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                if (input != null) {
2078bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    input.close();
2079bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2080bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2081bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2082bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2083bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2084bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2085bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2086bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private void writeTearDownApdusLocked() {
2087bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        FileOutputStream output = null;
2088bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        DataOutputStream stream = null;
2089bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2090bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2091bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            output = openFileOutput(TEAR_DOWN_SCRIPTS_FILE_NAME, Context.MODE_PRIVATE);
2092bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            stream = new DataOutputStream(output);
2093bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2094bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            stream.writeInt(mTearDownApdus.size());
2095bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2096bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            for (String packageName : mTearDownApdus.keySet()) {
2097bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                stream.writeUTF(packageName);
2098bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2099bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                List<byte[]> commands = mTearDownApdus.get(packageName).get();
2100bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                stream.writeInt(commands.size());
2101bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2102bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                for (byte[] cmd : commands) {
2103bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    stream.writeInt(cmd.length);
2104bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    stream.write(cmd, 0, cmd.length);
2105bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2106bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2107bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2108bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2109bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2110bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2111bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                if (output != null) {
2112bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    stream.flush();
2113bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    stream.close();
2114bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2115bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2116bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2117bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2118bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2119bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2120bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2121f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2122f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2123f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2124f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2125f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2126f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2127f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2128f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2129f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2130f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2131f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2132f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2133f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2134f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2135f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2136f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2137f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
21390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
21402f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
21410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
21422f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
21434acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
21442f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
21454acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
21462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
21472f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
21482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
214957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
215157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
215357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
215557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
215657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
215757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
215857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
216057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
216457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
216657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
216757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
216857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
216957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
217057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
217157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
217257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
217357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
217457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
217557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
217657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
217757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
217857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
217957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
218057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
218157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
218257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
218357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
218457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
218557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
218657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
218757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
218857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
218957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
219157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
219257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
219357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
219457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
219557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
219657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
219757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
21980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
22022f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
220374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
220474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22142f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2226b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2227b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2228b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2230b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2234bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2235bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2236bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2237bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2244d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2245d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2246d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2247d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
22481be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22491be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22501be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22511be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2252d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2253d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2254d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2255d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2256d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2257d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2258d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2259d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2260d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2261d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2262d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2263d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
22641be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22651be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22661be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22671be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2268d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2269d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2270d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2271d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2272d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2273d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2274d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
22750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
22760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
22770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
22780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
22810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2283ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
22840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
22850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
228757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2288b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
228957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
229057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2291b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2292b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2293b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2294b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2295b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2296b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2297b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2298b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    final class NfcServiceHandler extends Handler {
2299232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2300232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
2301232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            // Try to find NDEF on any of the technologies.
2302232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] technologies = nativeTag.getTechList();
2303232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int[] handles = nativeTag.getHandleList();
2304232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int techIndex = 0;
2305232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            int lastHandleScanned = 0;
2306232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            boolean ndefFoundAndConnected = false;
2307232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            NdefMessage[] ndefMsgs = null;
2308eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen            boolean foundFormattable = false;
2309e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableHandle = 0;
2310e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            int formattableTechnology = 0;
2311232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2312232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
2313232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                if (handles[techIndex] != lastHandleScanned) {
2314232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    // We haven't seen this handle yet, connect and checkndef
2315232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    if (nativeTag.connect(technologies[techIndex])) {
2316eb488e0b323ec2d4fe03528e2b9f3a73e66ae17dMartijn Coenen                        // Check if this type is NDEF formatable
2317434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        if (!foundFormattable) {
2318434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            if (nativeTag.isNdefFormatable()) {
2319434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                foundFormattable = true;
2320434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableHandle = nativeTag.getConnectedHandle();
2321434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                formattableTechnology = nativeTag.getConnectedTechnology();
2322434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // We'll only add formattable tech if no ndef is
2323434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // found - this is because libNFC refuses to format
2324434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                                // an already NDEF formatted tag.
2325434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            }
2326434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                            nativeTag.reconnect();
2327434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen                        } // else, already found formattable technology
2328434bb34457422a9cad664b73ed0d425db4a3093dMartijn Coenen
2329232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        int[] ndefinfo = new int[2];
2330232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        if (nativeTag.checkNdef(ndefinfo)) {
2331232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            ndefFoundAndConnected = true;
2332232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            boolean generateEmptyNdef = false;
2333232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2334232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int supportedNdefLength = ndefinfo[0];
2335232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            int cardState = ndefinfo[1];
2336232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            byte[] buff = nativeTag.read();
2337232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            if (buff != null) {
2338232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                ndefMsgs = new NdefMessage[1];
2339232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                try {
2340232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    ndefMsgs[0] = new NdefMessage(buff);
2341232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.addNdefTechnology(ndefMsgs[0],
2342ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                            nativeTag.getConnectedHandle(),
23430a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                            nativeTag.getConnectedLibNfcType(),
2344f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                            nativeTag.getConnectedTechnology(),
2345232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                            supportedNdefLength, cardState);
2346232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                    nativeTag.reconnect();
2347232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                } catch (FormatException e) {
2348232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   // Create an intent anyway, without NDEF messages
2349232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                   generateEmptyNdef = true;
2350232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                }
2351232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            } else {
2352232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                                generateEmptyNdef = true;
2353232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
2354232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2355232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           if (generateEmptyNdef) {
2356232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               ndefMsgs = new NdefMessage[] { };
2357ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                               nativeTag.addNdefTechnology(null,
2358ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       nativeTag.getConnectedHandle(),
23590a58617a63e32d2f43e3aabc705fb7b9de464482Martijn Coenen                                       nativeTag.getConnectedLibNfcType(),
2360f34ea55002a5f7fbe8486c6ab6f4a17481a9558fMartijn Coenen                                       nativeTag.getConnectedTechnology(),
2361ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                                       supportedNdefLength, cardState);
2362232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                               nativeTag.reconnect();
2363232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                           }
2364232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        } // else, no NDEF on this tech, continue loop
2365232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    } else {
2366232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // Connect failed, tag maybe lost. Try next handle
2367232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                        // anyway.
2368232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                    }
2369232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2370232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                lastHandleScanned = handles[techIndex];
2371232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                techIndex++;
2372232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            }
2373e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            if (ndefMsgs == null && foundFormattable) {
2374e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // Tag is not NDEF yet, and found a formattable target,
2375e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                // so add formattable tech to tech list.
2376e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                nativeTag.addNdefFormatableTechnology(
2377e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableHandle,
2378e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen                        formattableTechnology);
2379e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
2380232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2381232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen            return ndefMsgs;
2382232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
2383232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2384b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2385b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2386f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2387b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2388b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2389b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2390b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2391b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
239257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
239357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
23943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton               dispatchTag(tag, new NdefMessage[] { ndefMsg });
239557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
239657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
239757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2398f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2399ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2400f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2401232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2402232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2403232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
240498eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2405232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2406232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2407232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2408232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
240998eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
24103fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2411232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2412232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2413232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2414f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2415f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2416f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
24173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2418f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2419ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2420f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
242149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
242249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
242349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
242449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
242549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
242693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2427f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2428f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2429f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2430f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2431f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2432f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2433f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2434f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2435ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2436f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2437f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2438f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2439f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2440f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2441ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2442663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2443663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2444eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2445eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2446eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2447eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2448eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2449b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2450b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2451f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2452ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2453f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2454b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2455eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
24567f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
24577f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2458f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2459f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2460f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2461ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2462f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2463f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2464f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2465f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2466ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2467663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2468663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2469eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2470eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
24716f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2472ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2473f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2474b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2475f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2476f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2477f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2478eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2479eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2480eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2481663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2482663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2483663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2484663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2485663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2486663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2487663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2488663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2489663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2490663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2491663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2492663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2493cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2494eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2495f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2496f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2497f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2498f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2499f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2500ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2501f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2502f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2503f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2504f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2505f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2506ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2507f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2508f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2509ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2510f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2511f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2512f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
251357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
251457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
251557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
251657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
251757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
251857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
251957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
252057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
252157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
252257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
252357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
252457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
252557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
252657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2527c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2528c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2529c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
253049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
2531c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
253293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2533c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2534c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2535c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2536c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2537c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2538c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
253949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
2540c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
254193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2542c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2543c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2544c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2545f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2546f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2547f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2548f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2549b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2550d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
25513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
25523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent = new Intent(action);
2553b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
2554b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
2555b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
2556b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2557d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return intent;
2558d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
25593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
25613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
25620c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
256310389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            registerTagObject(nativeTag);
256410389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            if (!dispatchTag(tag, msgs)) {
256510389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen                unregisterObject(nativeTag.getHandle());
25663fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
25673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25683fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25693fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25703fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public byte[] concat(byte[]... arrays) {
25713fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int length = 0;
25723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
25733fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                length += array.length;
25743fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25753fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] result = new byte[length];
25763fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            int pos = 0;
25773fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            for (byte[] array : arrays) {
25783fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                System.arraycopy(array, 0, result, pos, array.length);
25793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                pos += array.length;
25803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return result;
25823fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private Uri parseWellKnownUriRecord(NdefRecord record) {
25853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] payload = record.getPayload();
25863fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
25873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            /*
25883fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[0] contains the URI Identifier Code, per the
25893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * NFC Forum "URI Record Type Definition" section 3.2.2.
25903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             *
25913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * payload[1]...payload[payload.length - 1] contains the rest of
25923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             * the URI.
25933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton             */
25943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
25953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
25963fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    Arrays.copyOfRange(payload, 1, payload.length));
25973fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            return Uri.parse(new String(fullUri, Charsets.UTF_8));
25983fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
25993fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26003fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
26013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            short tnf = record.getTnf();
26023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            byte[] type = record.getType();
2603adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            try {
2604adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                switch (tnf) {
2605adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_MIME_MEDIA: {
2606adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setType(new String(type, Charsets.US_ASCII));
26073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        return true;
2608adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
2609adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_ABSOLUTE_URI: {
2610adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        intent.setData(Uri.parse(new String(record.getPayload(), Charsets.UTF_8)));
2611adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return true;
2612adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    }
2613adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    case NdefRecord.TNF_WELL_KNOWN: {
2614adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        byte[] payload = record.getPayload();
2615adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (payload == null || payload.length == 0) return false;
2616adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
2617adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setType("text/plain");
2618adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2619adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
2620adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // Parse the smart poster looking for the URI
2621adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            try {
2622adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                NdefMessage msg = new NdefMessage(record.getPayload());
2623adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                for (NdefRecord subRecord : msg.getRecords()) {
2624adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    short subTnf = subRecord.getTnf();
2625adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    if (subTnf == NdefRecord.TNF_WELL_KNOWN
2626adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                            && Arrays.equals(subRecord.getType(),
2627adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                    NdefRecord.RTD_URI)) {
2628adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(parseWellKnownUriRecord(subRecord));
2629adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2630adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) {
2631adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        intent.setData(Uri.parse(new String(subRecord.getPayload(),
2632adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                                Charsets.UTF_8)));
2633adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                        return true;
2634adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                    }
26353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                                }
2636adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            } catch (FormatException e) {
2637adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                                return false;
26383fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                            }
2639adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
2640adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            intent.setData(parseWellKnownUriRecord(record));
2641adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
26423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                        }
2643adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        return false;
26443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
26453fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
2646adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
2647adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton            } catch (Exception e) {
2648adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                Log.e(TAG, "failed to parse record", e);
2649adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                return false;
26503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
26523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
26533fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        /** Returns false if no activities were found to dispatch to */
26543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
26553fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (DBG) {
26563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, "Dispatching tag");
26573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.d(TAG, tag.toString());
26583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
26593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
266005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            IntentFilter[] overrideFilters;
266105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            PendingIntent overrideIntent;
266224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] overrideTechLists;
2663a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            boolean foregroundNdefPush = mNdefPushClient.getForegroundMessage() != null;
266405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            synchronized (mNfcAdapter) {
266505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideFilters = mDispatchOverrideFilters;
266605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                overrideIntent = mDispatchOverrideIntent;
266724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                overrideTechLists = mDispatchOverrideTechLists;
266805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
266905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
267005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            // First look for dispatch overrides
2671a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (overrideIntent != null) {
267205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
267349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
267424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters,
267524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideTechLists)) {
267605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        if (DBG) Log.d(TAG, "Dispatched to override");
267705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        return true;
267805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
267905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch override registered, but no filters matched");
268005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (CanceledException e) {
268105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    Log.w(TAG, "Dispatch overrides pending intent was canceled");
268205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    synchronized (mNfcAdapter) {
268305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideFilters = null;
268405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                        mDispatchOverrideIntent = null;
268524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mDispatchOverrideTechLists = null;
268605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
268705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
268805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
268905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
2690a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // If there is not foreground NDEF push setup try a normal dispatch.
2691a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            //
2692a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // This is avoided when disabled in the NDEF push case to avoid the situation where each
2693a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // user has a different app in the foreground, causing each to launch itself on the
2694a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // remote device and the apps swapping which is in the foreground on each phone.
2695a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (!foregroundNdefPush) {
2696a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                try {
269724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return dispatchTagInternal(tag, msgs, null, null, null);
2698a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } catch (CanceledException e) {
2699a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.e(TAG, "CanceledException unexpected here", e);
2700a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2701a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
270205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
2703a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2704a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            return false;
270505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
270605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
270724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        /** Returns true if the tech list filter matches the techs on the tag */
270824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        private boolean filterMatch(String[] tagTechs, String[] filterTechs) {
270924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (filterTechs == null || filterTechs.length == 0) return false;
271024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
271124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            for (String tech : filterTechs) {
271224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (Arrays.binarySearch(tagTechs, tech) < 0) {
271324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    return false;
271424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
271524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
271624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            return true;
271724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton        }
271824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
271905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        // Dispatch to either an override pending intent or a standard startActivity()
272005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
272124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                PendingIntent overrideIntent, IntentFilter[] overrideFilters,
272224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                String[][] overrideTechLists)
272305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                throws CanceledException{
27243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Intent intent;
272524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
272624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
272724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Try the NDEF content specific dispatch
272824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            if (msgs != null && msgs.length > 0) {
27303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefMessage msg = msgs[0];
27313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                NdefRecord[] records = msg.getRecords();
27323fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                if (records.length > 0) {
27333fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    // Found valid NDEF data, try to dispatch that first
27343fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    NdefRecord record = records[0];
27353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
27363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
2737adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                    if (setTypeOrDataFromNdef(intent, record)) {
2738adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        // The record contains filterable data, try to start a matching activity
273924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (startDispatchActivity(intent, overrideIntent, overrideFilters,
274024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                                overrideTechLists)) {
2741adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            // If an activity is found then skip further dispatching
2742adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            return true;
2743adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        } else {
2744adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                            if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
2745adb527a9ce286d019d766a3b207a2251dea89bd1Jeff Hamilton                        }
27463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                    }
27473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                }
27483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
27493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
275024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
27513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the technology specific dispatch
275224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
275324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[] tagTechs = tag.getTechList();
275424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            Arrays.sort(tagTechs);
275524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
275624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (overrideIntent != null) {
275724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // There are dispatch overrides in place
275824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideTechLists != null) {
275924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    for (String[] filterTechs : overrideTechLists) {
276024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (filterMatch(tagTechs, filterTechs)) {
276124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            // An override matched, send it to the foreground activity.
276224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            intent = buildTagIntent(tag, msgs,
27638d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                                    NfcAdapter.ACTION_TECH_DISCOVERED);
276424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            overrideIntent.send(mContext, Activity.RESULT_OK, intent);
276524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            return true;
276624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        }
276724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
276824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
276905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
277024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Standard tech dispatch path
277124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
277224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                ArrayList<ComponentInfo> registered = mTechListFilters.getComponents();
277349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
277424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                // Check each registered activity to see if it matches
277524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                for (ComponentInfo info : registered) {
277624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Don't allow wild card matching
277724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    if (filterMatch(tagTechs, info.techs)) {
27783ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        // Add the activity as a match if it's not already in the list
27793ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        if (!matches.contains(info.resolveInfo)) {
27803ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                            matches.add(info.resolveInfo);
27813ca2b3f925d434559300ee2fb10bfcdd365a0fb6Jeff Hamilton                        }
278224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
278324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
278449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
278524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (matches.size() == 1) {
278624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Single match, launch directly
27878d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                    intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED);
278824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    ResolveInfo info = matches.get(0);
278924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
279024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
279124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
279224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
279324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
279424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
279524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
279624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (matches.size() > 1) {
279724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // Multiple matches, show a custom activity chooser dialog
279824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent = new Intent(mContext, TechListChooserActivity.class);
279924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
280024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putExtra(Intent.EXTRA_INTENT,
28018d69f5205e3c4a7c2eb869bbf4983d3d9fe45ab0Nick Pelly                            buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED));
280224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
280324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                            matches);
280424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    try {
280524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        mContext.startActivity(intent);
280624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        return true;
280724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    } catch (ActivityNotFoundException e) {
280824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                        if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
280924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    }
281024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else {
281124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                    // No matches, move on
281249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    if (DBG) Log.w(TAG, "No activities for technology handling");
281324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                }
28143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
281624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            // Try the generic intent
281824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            //
28193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
282024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (startDispatchActivity(intent, overrideIntent, overrideFilters, overrideTechLists)) {
28213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return true;
282205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
28233fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                Log.e(TAG, "No tag fallback activity found for " + intent);
28243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                return false;
28253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
28263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
282705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
282805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
282924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] overrideFilters, String[][] overrideTechLists)
283024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                throws CanceledException {
283105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            if (overrideIntent != null) {
2832a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                boolean found = false;
283324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                if (overrideFilters == null && overrideTechLists == null) {
2834a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    // No filters means to always dispatch regardless of match
2835a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    found = true;
283624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                } else if (overrideFilters != null) {
2837a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : overrideFilters) {
2838a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
2839a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            found = true;
2840a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            break;
2841a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
284205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    }
284305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
2844a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
2845a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (found) {
2846a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    Log.i(TAG, "Dispatching to override intent " + overrideIntent);
2847a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    overrideIntent.send(mContext, Activity.RESULT_OK, intent);
2848a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return true;
2849a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
2850a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    return false;
2851a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
285205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            } else {
285305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                try {
28541a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // If the current app called stopAppSwitches() then our startActivity()
28551a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // can be delayed for several seconds. This happens with the default home
28561a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // screen. As a system service we can override this behavior with
28571a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    // resumeAppSwitches()
28581a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                    mIActivityManager.resumeAppSwitches();
28591a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                } catch (RemoteException e) { }
28601a9eca5f84036d7dd3e28000290caa2f641856deNick Pelly                try {
286105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    mContext.startActivity(intent);
286205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return true;
286305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                } catch (ActivityNotFoundException e) {
286405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                    return false;
286505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton                }
286605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            }
286705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
2868b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2869b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2870b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
287149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
28727c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2873fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
28747c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        protected Void doInBackground(Boolean... enable) {
2875df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly            if (enable != null && enable.length > 0 && enable[0]) {
2876161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2877161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = true;
287849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
2879161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
28807c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2881533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2882161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2883161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                    mScreenOn = false;
288449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
28852436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    maybeDisconnectTarget();
2886161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2887533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
28887c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
28897c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
28907c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
28917c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
28927c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
28930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
28940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
28950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2896eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2897f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2898ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
28990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
290149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2902f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
290365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
29047c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
29057c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
29067c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
29077c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
290809f28764768ce0236cc3faf3dba17b1bbd6c8fdfKenny Root                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
290965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
29107c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
29117c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
29127c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
29137c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2914df4e65b5dacb313e7d68bad797a843a175febbedNick Pelly                new EnableDisableDiscoveryTask().execute(new Boolean(false));
2915bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2916bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                int handle = mSecureElement.doOpenSecureElementConnection();
2917bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                if (handle == 0) {
2918bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    Log.e(TAG, "Could not open the secure element!");
2919bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    return;
2920bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2921bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2922bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                synchronized (NfcService.this) {
2923bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    for (String packageName : mTearDownApdus.keySet()) {
2924bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                        for (byte[] cmd : mTearDownApdus.get(packageName).get()) {
2925bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                            mSecureElement.doTransceive(handle, cmd);
2926bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                        }
2927bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2928bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2929bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2930bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                mSecureElement.doDisconnect(handle);
2931bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
29327a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
29337a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
29347a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
29357a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
29367a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
29377a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    ApduList apdus = null;
29387a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
29397a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
29407a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        apdus = mTearDownApdus.remove(packageName);
29417a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        if (apdus == null) {
29427a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                            return;
29437a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
29445e7b58d9c95a9074a42c3e4820e2467dfa85af10Jeff Hamilton
29455e7b58d9c95a9074a42c3e4820e2467dfa85af10Jeff Hamilton
29467a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        writeTearDownApdusLocked();
29477a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    }
2948bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
29497a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    int handle = mSecureElement.doOpenSecureElementConnection();
29507a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (handle == 0) {
29517a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        Log.e(TAG, "Could not open the secure element!");
29527a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        return;
29537a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    }
2954bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
29557a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    try {
29567a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        for (byte[] cmd : apdus.get()) {
29577a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                            mSecureElement.doTransceive(handle, cmd);
29587a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
29597a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    } finally {
29607a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        mSecureElement.doDisconnect(handle);
2961bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2962bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
296674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2967