NfcService.java revision c8288824e2f5513dfe59b78d5f3af7757a1945b4
1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License.
6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at
7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software
11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and
14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License.
15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellypackage com.android.nfc;
18f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpServiceSocket;
20d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpSocket;
2124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport com.android.nfc.RegisteredComponentCache.ComponentInfo;
22ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushClient;
23ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushServer;
248afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R;
25d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.Activity;
271a9eca5f84036d7dd3e28000290caa2f641856deNick Pellyimport android.app.ActivityManagerNative;
282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.app.IActivityManager;
30275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager;
3105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
3293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.app.PendingIntent.CanceledException;
33bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.app.StatusBarManager;
34b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
4224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo;
43160b03be2e1ce574d228a2564d21c5f13f8c7b53Martijn Coenenimport android.content.pm.PackageManager;
443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
45bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.nfc.ApduList;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
512094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5349d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
58f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
60f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
623fb14d0868594c78a777e805545209636814e223Martijn Coenenimport android.nfc.tech.TagTechnology;
6324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
649d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
651b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenenimport android.nfc.tech.TagTechnology;
667c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
67b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
68b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6949d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
70b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
71533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
7313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
74f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
75f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
77bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
78bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataOutputStream;
7957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
8057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
8157d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
8257d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
8424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
863ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
872436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
88bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
893ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
91bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
92bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
93ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
9476a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    static final String TAG = "NfcService";
95fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
97a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
9913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
10013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
10113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
10213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
103d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
104fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
105bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
106bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
107bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
108bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
109a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
11093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
111bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
112225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen    /*package*/ static final String PREF = "NfcServicePrefs";
113f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
117a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
118a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_LTO = "llcp_lto";
120e1fac398523a97e3bcf513393a91478d79a8763fSylvain Fonteneau    private static final int LLCP_LTO_DEFAULT = 150;
1210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_LTO_MAX = 255;
122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Maximum Information Unit */
1240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_MIU = "llcp_miu";
1250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_DEFAULT = 128;
1260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_MIU_MAX = 2176;
127f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** Well Known Service List */
1290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_WKS = "llcp_wks";
1300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_DEFAULT = 1;
1310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_WKS_MAX = 15;
132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_LLCP_OPT = "llcp_opt";
1340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_DEFAULT = 0;
1350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int LLCP_OPT_MAX = 3;
136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_A = "discovery_a";
1380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_A_DEFAULT = true;
139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_B = "discovery_b";
1410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_B_DEFAULT = true;
142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_F = "discovery_f";
1440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_F_DEFAULT = true;
145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_15693 = "discovery_15693";
1470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean DISCOVERY_15693_DEFAULT = true;
148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
150a989351c7383aa6b3a6086b10f32c39c1d28fa5dJeff Hamilton    private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    /** NFC Reader Discovery mode for enableDiscovery() */
1530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int DISCOVERY_MODE_READER = 0;
154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_LLCP_LTO = 0;
156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
1570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_MIU = 1;
158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
1590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_WKS = 2;
160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
1610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_LLCP_OPT = 3;
162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
1650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
1670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
1690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
1710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
174b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
175b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
176b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
177b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
178b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
17957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
18057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
181b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
182c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
183c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
184b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
18549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
18649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
18749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
18849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
18949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
19049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
19149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
19249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
19349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
19449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
19549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
19649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
19705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
19874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
19974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
20174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
20249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
20349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
20449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
20549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
20649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private static final int SECURE_ELEMENT_ID = 11259375;  //TODO: remove hard-coded value
2070bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
20849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
20949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
2100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
2112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
2122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
2132f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
214275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private boolean mScreenUnlocked;
215a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private String mSePackageName;
2162f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2172f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
21805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
2190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
2200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
2210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
222533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
223ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
224ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
22576a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    private NfcDispatcher mNfcDispatcher;
226275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private KeyguardManager mKeyguard;
227d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
228d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
229d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
23193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
23293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
23393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
23493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
23593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
23693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
23793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
23893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
23993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
24093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
24193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
24293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
243d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
244d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
245d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
253d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
254d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
256275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mManager = new NativeNfcManager(this, this);
2570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
25874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
259ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
260ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
26176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly        mNfcDispatcher = new NfcDispatcher(this, mNdefPushClient);
26224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
2630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
265275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
2660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
268d6fdd3fbb880f1503d56616608e6823b51320dc3Nick Pelly        mIsNfcEnabled = false;  // real preference read later
269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
270275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
271275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
272533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
273275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
274275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
275533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
276d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
278eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
27965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
28065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
281bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
282275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        filter.addAction(Intent.ACTION_USER_PRESENT);
283275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
284bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
285bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
286bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
287bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
288bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
289275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
2900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
2940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
2960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
298a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
3052f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3062f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3123ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3133ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3144acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
315fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
31793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
3230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
328fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
33193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
333ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
336aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                isSuccess = _disable(previouslyEnabled);
337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
341fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
34205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
34324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
344a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
34505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
346a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
347a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
348a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
349ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
350ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
351a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
352a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
353a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
354a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
355a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
356a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
357a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
358a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
359a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
360a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
361a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
362a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
363a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
364a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
36524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
36624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
36724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
36824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
36924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
37049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
37176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists);
37205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
37305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
37405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
37505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
37605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
37776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly
37876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
37905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
38005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
38105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
382ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
383ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
384ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
385ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
386ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
387ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
388ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
389ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
390ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
391ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
392ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
3932094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
3942094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
3952094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
3962094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
3972094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
3982094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
3992094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (mNdefPushClient.setForegroundCallback(callback)) {
4002094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
4012094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
4022094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
4032094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
4042094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
405ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
406ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4072094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadMsg = mNdefPushClient.setForegroundMessage(null);
4082094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadCallback = mNdefPushClient.setForegroundCallback(null);
4092094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
410ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
411ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
412ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
413ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
414ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
416d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
417bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
4240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
4261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
4271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
4301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4331878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4401878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4411878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4421878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4461878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4471878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
451f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
454fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
457d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
458bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
459f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
461f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
463f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4641878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
4650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4661878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
4671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4701878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4791878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4801878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4811878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4821878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4861878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4871878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
489f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
490f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
491fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
4930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
494d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
495bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
496f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
5021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
503bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
5041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
5140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
5171878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
5181878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
5201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
530f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
532fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
534d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
5360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
537bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
538fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
540d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
543f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
544fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
546d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
5480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
550fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
552d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
5540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
556fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
558d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
5600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
562fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
564d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
568bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
56949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
57093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
57149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
5720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
5730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
574fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public String getProperties(String param) throws RemoteException {
576d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null) {
5790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
5800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
5810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
5830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
5840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
5850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
5870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
5890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
5900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
5910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
5920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
5930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
5950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
5960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
5970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
5980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
5990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return "Unknown property";
602f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
603f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
605fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
610fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int setProperties(String param, String value) throws RemoteException {
61293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
6130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (isEnabled()) {
6150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NFC_ON;
6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            int val;
6190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check params validity */
6210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param == null || value == null) {
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
6230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
6240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_LTO_MAX)
6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_LTO, val);
6342f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_MIU, val);
6482f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_WKS_MAX)
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_WKS, val);
6622f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
6660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                val = Integer.parseInt(value);
6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Check params */
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (val > LLCP_OPT_MAX)
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_INVALID_PARAM;
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putInt(PREF_LLCP_OPT, val);
6762f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
6820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
6830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
6862f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
6900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
6930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
6962f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
6970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
7062f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
7100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
7162f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean b = Boolean.parseBoolean(value);
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Store value */
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
7262f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick                mPrefsEditor.apply();
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* Update JNI */
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_INVALID_PARAM;
733f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.SUCCESS;
736f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
737d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
738d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
739d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
74057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
74157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
74257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
74357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
74457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
745d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
746d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
747d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
748d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
74993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
75057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
75157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
75257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
75357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
75457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
75557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
75657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
75757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
75857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
75957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
76057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
76157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
76257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
76357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
76457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
76557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
76657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
76757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
76857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
76957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
77057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
77157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
77257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
77357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
77457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
77557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
77657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
77757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
77857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
77957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
78057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
78157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
78257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
78357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
78457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
78557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
78657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
78757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
78857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
78957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
790d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
7913fb14d0868594c78a777e805545209636814e223Martijn Coenen
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
795f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
796f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
797bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
798bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
799f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
800f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
801bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
802f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
803f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
804fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
806d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
807bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
808f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
811f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
812f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
813f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
814f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
815f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
816f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
817f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
8181878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
8191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
8201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
8211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
822f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
824f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
825f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
826f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
827fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
829d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
830bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
833f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
834f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
835f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
836f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
837f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
838f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
839f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
840f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
841f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
84293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
845f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
846f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
847f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
848f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
849f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
850f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
852f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
853f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
854fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
856d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
857bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
858f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
859f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
860f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
861f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
862f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
863f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
864f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
865f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
866f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
867f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
868f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
86993915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
870f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
871f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
872f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
873f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
874f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
875f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
876f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
877f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
8780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
881fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
883d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
884bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
8850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
886f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
887f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
888f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
889f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
890f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
8920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
893f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
896f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
898f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
899f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
901fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
903d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
904bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
906f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
9090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
913f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
914f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
9160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
921fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
923d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
924bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
9250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
926f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
928f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
930f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
933f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
941fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
943d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
9460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
953f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
9560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
9570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
9580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
9590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
9620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
965fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
967d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
9700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
977f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
9800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
9810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
9820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
9830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
9860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
989fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
991d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
9940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1001f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
100328f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
10040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
100528f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
10060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1009fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
1011d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
10140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
10150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1022f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
10250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
10270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
10290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
10310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
10320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
10350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
10370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1038f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
1039bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1040bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
1041f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1042f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1043bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
1044f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1045f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1046fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
1048d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
10510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
10560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
1059f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
10600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
106193915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
10620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
10630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
10640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
10652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
10661878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
10671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
10681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
10692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
10700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
10710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
10720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
10730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
10750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
10770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
1078fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
10790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
1080d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
10810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
10830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
10850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
10860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
10870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
10890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
1090f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
10910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
10921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
1093f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
10940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
10950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
10960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
10970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
10980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1101f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
1102f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1103f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
1104bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
1105bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
1106f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
1107f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
1108bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
1109f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
1110f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
1111fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1112f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
1113d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1114bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1119f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1120f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1123f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
11251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
11261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
11271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
1128f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1129f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1131fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1133d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1134bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1138f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1143f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1151fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1152f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1153d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1154bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1164f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1165f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1176fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1178d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1179bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1189f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1205fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1207d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1208bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1219b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1220b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
122121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1222b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
122549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1229fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1230ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1231d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1232bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1242b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1243b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1245ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
12461b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            if (technology == TagTechnology.NFC_B) {
12471b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen                return ErrorCodes.ERROR_NOT_SUPPORTED;
12481b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            }
12491b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen
1250ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1251ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1252ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1253ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1254ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1255ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1256ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1257ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1259f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1260fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1261aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1262aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1263aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1264aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1265aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1266aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1267aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1268aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1269aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1270aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1271aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1272aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1273aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1274aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1275aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1276aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1277aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1278aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1279aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1280aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1281aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1282aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1283aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1284b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1285d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1286bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1293b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1295b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1300fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1318f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1319fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1320b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1321b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1322b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1323b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1324b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1325b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1326b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1327b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1328b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1329b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1330b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1331b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1332b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1333b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1334ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1335b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1336b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1337fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1345f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1347f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
13493ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
13513ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1352f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1353f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1356fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13579d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
135897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1359d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1360bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1362f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1366f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1367f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
13729d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
13739d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
13749d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
13759d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
13769d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
13779d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
13789d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1383fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1385d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1386bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1388f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1392f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1397b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1400f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1411fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1413d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1414bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1416f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1420f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1421f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1422f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1424f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1426f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1428b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1430f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1433f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1437fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1439bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1442fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
14443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1445f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1447fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
144903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
145003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
145103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
145203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
145303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
145403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
145503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
145603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
145703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
145803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
145903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
146003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
146103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
146203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
146303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
146403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
146503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
146603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
146703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
146803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
146903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
14730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
14740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
14750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
14760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
14770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
14780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
14790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
14800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
14810aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
14820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
14830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
14840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
14850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
14860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
14870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
14880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
14890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
14900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
14910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
14920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
14930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
14940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
14950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
14960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
14971b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
14983fb14d0868594c78a777e805545209636814e223Martijn Coenen        public Tag rediscover(int nativeHandle) throws RemoteException {
14993fb14d0868594c78a777e805545209636814e223Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15003fb14d0868594c78a777e805545209636814e223Martijn Coenen
15013fb14d0868594c78a777e805545209636814e223Martijn Coenen            NativeNfcTag tag = null;
15023fb14d0868594c78a777e805545209636814e223Martijn Coenen
15033fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Check if NFC is enabled
15043fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (!mIsNfcEnabled) {
15053fb14d0868594c78a777e805545209636814e223Martijn Coenen                return null;
15063fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
15073fb14d0868594c78a777e805545209636814e223Martijn Coenen
15083fb14d0868594c78a777e805545209636814e223Martijn Coenen            /* find the tag in the hmap */
15093fb14d0868594c78a777e805545209636814e223Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
15103fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (tag != null) {
15113fb14d0868594c78a777e805545209636814e223Martijn Coenen                // For now the prime usecase for rediscover() is to be able
15123fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to access the NDEF technology after formatting without
15133fb14d0868594c78a777e805545209636814e223Martijn Coenen                // having to remove the tag from the field, or similar
15143fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to have access to NdefFormatable in case low-level commands
15153fb14d0868594c78a777e805545209636814e223Martijn Coenen                // were used to remove NDEF. So instead of doing a full stack
15163fb14d0868594c78a777e805545209636814e223Martijn Coenen                // rediscover (which is poorly supported at the moment anyway),
15173fb14d0868594c78a777e805545209636814e223Martijn Coenen                // we simply remove these two technologies and detect them
15183fb14d0868594c78a777e805545209636814e223Martijn Coenen                // again.
15193fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF);
15203fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
15213fb14d0868594c78a777e805545209636814e223Martijn Coenen                NdefMessage[] msgs = findAndReadNdef(tag);
15223fb14d0868594c78a777e805545209636814e223Martijn Coenen                // Build a new Tag object to return
15233fb14d0868594c78a777e805545209636814e223Martijn Coenen                Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
15243fb14d0868594c78a777e805545209636814e223Martijn Coenen                        tag.getTechExtras(), tag.getHandle(), mNfcTagService);
15253fb14d0868594c78a777e805545209636814e223Martijn Coenen                return newTag;
15263fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
15273fb14d0868594c78a777e805545209636814e223Martijn Coenen            return null;
15283fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
15293fb14d0868594c78a777e805545209636814e223Martijn Coenen
15303fb14d0868594c78a777e805545209636814e223Martijn Coenen
15313fb14d0868594c78a777e805545209636814e223Martijn Coenen        @Override
15321b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
15331b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15341b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
15351b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
15361b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15381b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
1539dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void setFelicaTimeout(int timeout) throws RemoteException {
15401b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
15411b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
1542dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mManager.setFelicaTimeout(timeout);
1543dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        }
1544dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1545dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        @Override
1546dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void resetTimeouts() throws RemoteException {
1547dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1548dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1549dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mManager.resetTimeouts();
15501b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
15510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1552f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1554f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1555fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1557d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1560f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
15640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1565f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
15700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
15710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
15720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
15730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1576f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1577fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1579d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1580f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
15860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1587f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
15920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1593f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1596fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1598d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1599f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1601f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
16050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1606f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
16110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
16120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
16130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
16140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
161649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
16170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1619f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1620fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1622d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1626f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1631f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
16360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
16380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1640f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1643fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1645d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
16520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
16580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
16590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
16600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
16620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1664fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1666d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1667f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1670f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
16740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1675f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
16770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
16780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
16800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1681b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
16820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
168349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
16840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
16860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1687f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1690fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1692d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1693f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
16960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1699f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1700f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
17050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1711f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1712fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
17130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1714d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1715f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1717f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1721f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1722f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
17270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
17290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1730f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1731fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
173297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
173397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1734d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1735f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1737f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
17390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
17400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1741f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1742f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
17440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
17450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
17460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
17470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
17480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
17490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
17500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
17510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
17520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
17530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1754f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1755dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
1756dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // Blocks until a pending open() or transceive() times out.
1757dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        //TODO: This is incorrect behavior - the close should interrupt pending
1758dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // operations. However this is not supported by current hardware.
1759dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1760dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        synchronized(NfcService.this) {
1761dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (!mIsNfcEnabled) {
1762dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC adapter is disabled");
1763dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1764dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (mOpenEe == null) {
1765dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC EE closed");
1766dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1767dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
1768dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new SecurityException("Wrong PID");
1769dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1770dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1771c8288824e2f5513dfe59b78d5f3af7757a1945b4Nick Pelly            mManager.resetTimeouts();
1772dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mSecureElement.doDisconnect(mOpenEe.handle);
1773dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mOpenEe = null;
1774dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1775dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            applyRouting();
1776dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        }
1777dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    }
1778dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
177949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
178049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
178149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
178249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
178349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
178449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
178549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
178649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
178749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
178849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
178949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
179049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
17910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1792bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
179349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
179493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1795bd555ee64250126b60b24814120a2049943920caNick Pelly
179649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
179749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
179849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
179949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
180049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
180149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
180349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
180449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
180649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
180749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
180849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
180949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
181049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
181149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
181249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
181349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
181549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
181649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
181749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
181849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1819ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doSetIsoDepTimeout(10000);
1820ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
182149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
182249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
182349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
182449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
182549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
182649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
182749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
18280bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1830bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
183149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
183293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
18330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
183449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
183549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
1836dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                _nfcEeClose(true, getCallingPid());
183749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
183849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
183949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
184149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
184249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18430bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1844bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
184549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
184693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1847bd555ee64250126b60b24814120a2049943920caNick Pelly
184849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
184949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
185049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
185149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
185249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
185349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
185449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
185549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
18560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
185749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
185849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
18590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
186049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
186149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
186249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
186349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
186449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
186549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
186649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
186749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
186849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
186949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
187049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
18710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
18720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
187349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
18740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1876bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
187749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
187893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
187949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
18800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
18810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1882bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
188349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
188493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
188549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
188649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
18870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
1888bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1889bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1890bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void registerTearDownApdus(String packageName, ApduList apdu) throws RemoteException {
1891bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1892a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
1893a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
1894bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1895bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1896bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
1897bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        public void unregisterTearDownApdus(String packageName) throws RemoteException {
1898bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1899a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.w(TAG, "NOP");
1900a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            //TODO: Remove this API
1901bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
19020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
19030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
190449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
190549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
190649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
190749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
190849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
190949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
191049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
191149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1912bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
191349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
191449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
191549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
191649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
19170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
1918dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                    _nfcEeClose(false, -1);
1919dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                } catch (IOException e) { /* already closed */ }
19200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
19210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
19220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
19230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
19240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
19256efda9f3970382554437be037aed863be9889499Sylvain Fonteneau        applyProperties();
19266efda9f3970382554437be037aed863be9889499Sylvain Fonteneau
19270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
19280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
192965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
193049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
193165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
19320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
193349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
193457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
1936ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
193757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
1938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
1939aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            Log.w(TAG, "Error enabling NFC");
19400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
1944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1948aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    private boolean _disable(boolean oldEnabledState) {
1949aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean isSuccess;
1950aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1951aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        /* tear down the my tag server */
1952aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mNdefPushServer.stop();
1953aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1954aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // Stop watchdog if tag present
1955aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // A convenient way to stop the watchdog properly consists of
1956aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // disconnecting the tag. The polling loop shall be stopped before
1957aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // to avoid the tag being discovered again.
1958aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mIsDiscoveryOn = false;
1959aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        applyRouting();
1960aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        maybeDisconnectTarget();
1961aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1962aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        isSuccess = mManager.deinitialize();
1963aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
1964aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (isSuccess) {
1965aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mIsNfcEnabled = false;
19668586b104c1cf07c52c739c0afab0ded1bf151859Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
1967aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mNdefPushClient.setForegroundMessage(null);
1968aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1969aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1970aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        updateNfcOnSetting(oldEnabledState);
1971aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1972aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        return isSuccess;
1973aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    }
1974aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
197549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
197649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
197749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
1978275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (mScreenUnlocked) {
197949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
198049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
198149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doSelectSecureElement(SECURE_ELEMENT_ID);
198249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
198349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
198449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
1985221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
198649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
198749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
198849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
198949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
199049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
199149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.disableDiscovery();
1992221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1993221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
199449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
199549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
199649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
199749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.disableDiscovery();
1998221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
199965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
200065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
200165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
20022436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
20032436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
20042436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
20052436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
20062436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
20072436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
2008663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
2009663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
20102436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
20112436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
20122436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
2013663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
2014663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
2015663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
2016663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2017663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
2018663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
2019663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2020663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
2021663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
2022663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
2023663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
2024663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
2025663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
20262436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
20272436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
20282436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
20292436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
2030a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
2031a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
2032a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2033a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
2034a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
2035a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2036a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
2037a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
2038a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
2039a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
2040bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2041a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
2042a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
2043a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
2044a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            executeSeReset();
2045a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
2046a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
2047a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2048a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
2049bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2050a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
2051a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
2052a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
2053a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
2054a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
2055a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2056a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2057aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2058aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean tempEnable = !mIsNfcEnabled;
2059aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
2060aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (!_enable(false)) {
2061aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                Log.w(TAG, "Could not enable NFC to reset EE!");
2062aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                return;
2063aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
2064aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
2065aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2066a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
2067a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
2068a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
2069a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
2070aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (tempEnable) {
2071aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                _disable(true);
2072aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
2073a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
2074a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
2075bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2076a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
2077a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
2078bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2079a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
2080a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
2081aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2082aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
2083aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            _disable(true);
2084aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
2085bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2086bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2087a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
2088a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
2089a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
2090bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2091bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2092a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
2093a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
2094bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2095a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
2096a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
2097bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2098a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
2099a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
2100bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2101a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
2102bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2103a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
2104a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
2105bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2106bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2107a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
2108a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
2109a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
2110bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2111a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
2112a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
2113bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2114bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2115a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
2116a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
2117bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2118bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2119bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2120bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2121bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2122a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
2123bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2124bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2125f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly    private void applyProperties() {
2126f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
2127f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
2128f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
2129f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
2130f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
2131f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
2132f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
2133f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
2134f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
2135f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
2136f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
2137f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
2138f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
2139f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly                mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
2140f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly     }
2141f5280191c0e422a730504eebeced4acbcfc1bd9fNick Pelly
21420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
21430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
21442f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
21450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
21462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
21474acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
21482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
21494acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
21502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
21512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
21522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
215357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
215557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
215757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
215857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
215957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
216057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
216157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
216457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
216657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
216757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
216857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
216957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
217057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
217157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
217257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
217357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
217457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
217557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
217657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
217757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
217857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
217957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
218057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
218157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
218257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
218357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
218457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
218557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
218657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
218757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
218857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
218957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
219057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
219157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
219257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
219357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
219457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
219557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
219657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
219757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
219857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
219957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
220057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
220157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
22020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
22062f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
220774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
220874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22182f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
2230b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
2231b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2232b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
22332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2234b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22372f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2238bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2239bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2240bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2241bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
2245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2248d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2249d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2250d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2251d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
22521be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22531be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22541be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22551be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2256d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2257d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2258d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2259d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2260d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2261d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2262d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2263d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2264d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2265d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2266d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2267d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
22681be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
22691be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
22701be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
22711be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2272d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2273d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2274d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2275d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2276d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2277d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2278d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
22790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
22800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
22810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
22820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
22840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
22850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2287ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
22880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
22890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
229157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2292b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
229357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
229457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2295b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2296b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2297b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2298b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2299b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2300b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2301b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
23023fb14d0868594c78a777e805545209636814e223Martijn Coenen    static public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
23033fb14d0868594c78a777e805545209636814e223Martijn Coenen        // Try to find NDEF on any of the technologies.
23043fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] technologies = nativeTag.getTechList();
23053fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] handles = nativeTag.getHandleList();
23063fb14d0868594c78a777e805545209636814e223Martijn Coenen        int techIndex = 0;
23073fb14d0868594c78a777e805545209636814e223Martijn Coenen        int lastHandleScanned = 0;
23083fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean ndefFoundAndConnected = false;
23093fb14d0868594c78a777e805545209636814e223Martijn Coenen        NdefMessage[] ndefMsgs = null;
23103fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean foundFormattable = false;
23113fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableHandle = 0;
23123fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableLibNfcType = 0;
23133fb14d0868594c78a777e805545209636814e223Martijn Coenen
23143fb14d0868594c78a777e805545209636814e223Martijn Coenen        while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
23153fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (handles[techIndex] != lastHandleScanned) {
23163fb14d0868594c78a777e805545209636814e223Martijn Coenen                // We haven't seen this handle yet, connect and checkndef
23173fb14d0868594c78a777e805545209636814e223Martijn Coenen                if (nativeTag.connect(technologies[techIndex])) {
23183fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Check if this type is NDEF formatable
23193fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (!foundFormattable) {
23203fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (nativeTag.isNdefFormatable()) {
23213fb14d0868594c78a777e805545209636814e223Martijn Coenen                            foundFormattable = true;
23223fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableHandle = nativeTag.getConnectedHandle();
23233fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableLibNfcType = nativeTag.getConnectedLibNfcType();
23243fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // We'll only add formattable tech if no ndef is
23253fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // found - this is because libNFC refuses to format
23263fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // an already NDEF formatted tag.
23273fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
23283fb14d0868594c78a777e805545209636814e223Martijn Coenen                        nativeTag.reconnect();
23293fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, already found formattable technology
23303fb14d0868594c78a777e805545209636814e223Martijn Coenen
23313fb14d0868594c78a777e805545209636814e223Martijn Coenen                    int[] ndefinfo = new int[2];
23323fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (nativeTag.checkNdef(ndefinfo)) {
23333fb14d0868594c78a777e805545209636814e223Martijn Coenen                        ndefFoundAndConnected = true;
23343fb14d0868594c78a777e805545209636814e223Martijn Coenen                        boolean generateEmptyNdef = false;
23353fb14d0868594c78a777e805545209636814e223Martijn Coenen
23363fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int supportedNdefLength = ndefinfo[0];
23373fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int cardState = ndefinfo[1];
23383fb14d0868594c78a777e805545209636814e223Martijn Coenen                        byte[] buff = nativeTag.read();
23393fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (buff != null) {
23403fb14d0868594c78a777e805545209636814e223Martijn Coenen                            ndefMsgs = new NdefMessage[1];
23413fb14d0868594c78a777e805545209636814e223Martijn Coenen                            try {
23423fb14d0868594c78a777e805545209636814e223Martijn Coenen                                ndefMsgs[0] = new NdefMessage(buff);
23433fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.addNdefTechnology(ndefMsgs[0],
23443fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedHandle(),
23453fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedLibNfcType(),
23463fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedTechnology(),
23473fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        supportedNdefLength, cardState);
23483fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.reconnect();
23493fb14d0868594c78a777e805545209636814e223Martijn Coenen                            } catch (FormatException e) {
23503fb14d0868594c78a777e805545209636814e223Martijn Coenen                               // Create an intent anyway, without NDEF messages
23513fb14d0868594c78a777e805545209636814e223Martijn Coenen                               generateEmptyNdef = true;
2352232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
23533fb14d0868594c78a777e805545209636814e223Martijn Coenen                        } else {
23543fb14d0868594c78a777e805545209636814e223Martijn Coenen                            generateEmptyNdef = true;
23553fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
2356232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
23573fb14d0868594c78a777e805545209636814e223Martijn Coenen                       if (generateEmptyNdef) {
23583fb14d0868594c78a777e805545209636814e223Martijn Coenen                           ndefMsgs = new NdefMessage[] { };
23593fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.addNdefTechnology(null,
23603fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedHandle(),
23613fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedLibNfcType(),
23623fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedTechnology(),
23633fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   supportedNdefLength, cardState);
23643fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.reconnect();
23653fb14d0868594c78a777e805545209636814e223Martijn Coenen                       }
23663fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, no NDEF on this tech, continue loop
23673fb14d0868594c78a777e805545209636814e223Martijn Coenen                } else {
23683fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Connect failed, tag maybe lost. Try next handle
23693fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // anyway.
2370232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2371e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
23723fb14d0868594c78a777e805545209636814e223Martijn Coenen            lastHandleScanned = handles[techIndex];
23733fb14d0868594c78a777e805545209636814e223Martijn Coenen            techIndex++;
2374232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
23753fb14d0868594c78a777e805545209636814e223Martijn Coenen        if (ndefMsgs == null && foundFormattable) {
23763fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Tag is not NDEF yet, and found a formattable target,
23773fb14d0868594c78a777e805545209636814e223Martijn Coenen            // so add formattable tech to tech list.
23783fb14d0868594c78a777e805545209636814e223Martijn Coenen            nativeTag.addNdefFormatableTechnology(
23793fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableHandle,
23803fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableLibNfcType);
23813fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
23823fb14d0868594c78a777e805545209636814e223Martijn Coenen
23833fb14d0868594c78a777e805545209636814e223Martijn Coenen        return ndefMsgs;
23843fb14d0868594c78a777e805545209636814e223Martijn Coenen    }
23853fb14d0868594c78a777e805545209636814e223Martijn Coenen
23863fb14d0868594c78a777e805545209636814e223Martijn Coenen
23873fb14d0868594c78a777e805545209636814e223Martijn Coenen    final class NfcServiceHandler extends Handler {
2388232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2389b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2390b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2391f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2392b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2393b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2394b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2395b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2396b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
239757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
239857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
239976a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly               mNfcDispatcher.dispatchTag(tag, new NdefMessage[] { ndefMsg });
240057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
240157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
240257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2403f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2404ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2405f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2406232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2407232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2408232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
240998eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2410232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2411232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2412232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2413232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
241498eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
24153fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2416232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2417232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2418232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2419f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2420f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2421f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
24223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2423f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2424ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2425f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
242649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
242749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
242849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
242949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
243049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
243193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2432f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2433f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2434f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2435f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2436f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2437f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2438f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2439f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2440ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2441f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2442f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2443f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2444f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2445f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2446ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2447663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2448663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2449eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2450eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2451eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2452eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2453eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2454b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2455b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2456f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2457ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2458f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2459b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2460eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
24617f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
24627f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2463f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2464f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2465f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2466ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2467f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2468f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2469f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2470f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2471ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2472663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2473663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2474eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2475eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
24766f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2477ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2478f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2479b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2480f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2481f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2482f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2483eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2484eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2485eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2486663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2487663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2488663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2489663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2490663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2491663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2492663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2493663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2494663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2495663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2496663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2497663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2498cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2499eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2500f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2501f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2502f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2503f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2504f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2505ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2506f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2507f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2508f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2509f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2510f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2511ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2512f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2513f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2514ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2515f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2516f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2517f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
251857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
251957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
252057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
252157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
252257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
252357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
252457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
252557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
252657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
252757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
252857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
252957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
253057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
253157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2532c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2533c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2534c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
253549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
2536c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
253793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2538c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2539c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2540c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2541c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2542c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2543c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
254449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
2545c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
254693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2547c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2548c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2549c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2550f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2551f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2552f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2553f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2554b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2555d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
25563fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
25573fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
25580c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
255910389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            registerTagObject(nativeTag);
256076a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            if (!mNfcDispatcher.dispatchTag(tag, msgs)) {
256110389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen                unregisterObject(nativeTag.getHandle());
25623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
25633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
25643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
2565b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2566b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2567b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
256849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
25697c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2570fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2571275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        protected Void doInBackground(Boolean... params) {
2572275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]);
2573275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2574275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (params != null && params.length > 0 && params[0]) {
2575161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2576275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (!mScreenUnlocked) {
2577275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = true;
2578275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2579275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2580275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring enable request");
2581275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2582161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
25837c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2584533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2585161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2586275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (mScreenUnlocked) {
2587275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = false;
2588275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2589275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        maybeDisconnectTarget();
2590275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2591275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring disable request");
2592275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2593161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2594533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
25957c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
25967c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
25977c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
25987c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
25997c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
26000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
26010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
26020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2603eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2605ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
26060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2607f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
260849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2609f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
261065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
26117c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
26127c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
26137c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
26147c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2615275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2616275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Only enable if the screen is unlocked. If the screen is locked
2617275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Intent.ACTION_USER_PRESENT will be broadcast when the screen is
2618275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // unlocked.
2619275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                boolean enable = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
2620275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2621275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(enable);
262265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
26237c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
26247c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
26257c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
26267c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2627275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.FALSE);
2628275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
2629275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // The user has unlocked the screen. Enabled!
2630275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
2631bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2632a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
2633bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
26347a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
26357a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
26367a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
26377a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
26387a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
26397a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
26407a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
2641a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                        if (packageName.equals(mSePackageName)) {
2642a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
26437a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
2644bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2645bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
264974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2650