NfcService.java revision f6c56a2191d58e3f9f68e3e7d94908b04b9b66ff
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;
21f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.DeviceHostListener;
22f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.NfcDepEndpoint;
23f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.TagEndpoint;
24ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushClient;
25ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushServer;
2681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpConnectionlessSocket;
2781c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpServiceSocket;
2881c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpSocket;
2981c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcManager;
3081c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcSecureElement;
318afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R;
32d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
34275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager;
3505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
36bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.app.StatusBarManager;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
4013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
4113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
502094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5249d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
58f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
6024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
619d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
6281c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology;
637c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
64b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
65b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6649d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
67b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
68533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
69f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
7013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
71f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7357d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
74bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
7557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
7857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
7924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
803ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
812436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
82bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
833ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
84f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonpublic class NfcService extends Application implements DeviceHostListener {
85bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
86bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
87ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
8876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    static final String TAG = "NfcService";
89fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
91a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
93d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
94fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
95bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
96bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
97bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
98bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
99a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
10093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
101bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
102225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen    /*package*/ static final String PREF = "NfcServicePrefs";
103f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
107a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
108a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
109b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
110b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
111b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
112b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
113b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
11457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
11557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
116b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
117c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
118c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
12049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
12149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
12249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
12349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
1247efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly
12549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
12649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
12749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
13149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
13249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
13374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
13474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
13674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
13749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
13849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
13949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
14049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
1410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
14249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
14349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
1440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1452f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
1462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
1472f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
148275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private boolean mScreenUnlocked;
149a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private String mSePackageName;
1502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
1512f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
15205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
153f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    private NativeNfcManager mDeviceHost;
1540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
1550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
156533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
157ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
158ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
15976a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    private NfcDispatcher mNfcDispatcher;
160275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private KeyguardManager mKeyguard;
161d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
162d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
163d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
16493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
16593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
16693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
16793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
16893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
16993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
17093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
17193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
17293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
17393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
17493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
17593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
17693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
177d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
178d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
179d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
182f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteEndpointDiscovered(TagEndpoint tag) {
183f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_NDEF_TAG, tag);
184f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
185f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
186f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
187f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies transaction
188f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
189f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onCardEmulationDeselected() {
190f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_TARGET_DESELECTED, null);
191f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
192f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
193f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
194f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies transaction
195f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
196f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onCardEmulationAidSelected(byte[] aid) {
197f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_CARD_EMULATION, aid);
198f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
199f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
200f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
201f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies P2P Device detected, to activate LLCP link
202f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
203f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    @Override
204f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onLlcpLinkActivated(NfcDepEndpoint device) {
205f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
206f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
207f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
208f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
209f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies P2P Device detected, to activate LLCP link
210f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
211f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
212f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
213f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
214f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
215f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteFieldActivated() {
216f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null);
217f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
218f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
219f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteFieldDeactivated() {
220f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null);
221f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
222f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
223f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    @Override
2240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2262f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
229d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
230d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
232f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mDeviceHost = new NativeNfcManager(this, this);
233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mDeviceHost.initializeNativeStructure();
23474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
235ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
236ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
23776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly        mNfcDispatcher = new NfcDispatcher(this, mNdefPushClient);
23824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
2390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
241275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2447efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly        mIsNfcEnabled = false;  // load from preferences later
245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
246275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
247275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
248533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
249275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
250275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
251533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
252d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
254eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
25565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
25665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
257bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
258275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        filter.addAction(Intent.ACTION_USER_PRESENT);
259275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
260bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
261bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
262bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
263bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
264bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
265275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
2660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
2700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
2710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
274a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
2770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
2780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2812f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
2822f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
2832f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
2840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
2850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
2883ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
2893ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
2904acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
291fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
29393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
2940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
2960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
2970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
2980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
2990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
304fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
30793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
309ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
312aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                isSuccess = _disable(previouslyEnabled);
313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
317fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
31805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
31924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
320a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
32105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
322a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
323a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
324a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
325ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
326ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
327a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
328a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
329a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
330a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
331a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
332a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
333a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
334a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
335a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
336a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
337a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
338a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
339a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
340a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
34124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
34224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
34324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
34424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
34524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
34649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
34776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists);
34805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
34905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
35005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
35105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
35205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
35376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly
35476a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
35505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
35605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
35705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
358ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
359ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
360ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
361ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
362ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
363ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
364ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
365ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
366ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
367ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
368ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
3692094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
3702094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
3712094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
3722094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
3732094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
3742094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
3752094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (mNdefPushClient.setForegroundCallback(callback)) {
3762094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
3772094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
3782094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
3792094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
3802094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
381ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
382ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
3832094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadMsg = mNdefPushClient.setForegroundMessage(null);
3842094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadCallback = mNdefPushClient.setForegroundCallback(null);
3852094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
386ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
387ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
388ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
389ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
390ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
3910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
392d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
393bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
4000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
4021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
4031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
405f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpConnectionlessSocket(sap);
4061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
415f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
417f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
4181878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
427f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
428f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
430fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
4320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
433d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
434bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
437f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4401878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
4410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
442f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
4431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4461878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
450f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    return mGeneratedSocketHandle;
451f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
454f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
4551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4561878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4571878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4581878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
466f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
467fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
4690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
470d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
471bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
474f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
4781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
479bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
480f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4821878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4871878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4881878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4891878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
4900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
493f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
4941878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4951878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
4961878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4981878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4991878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5001878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
507f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
508fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
510d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
5120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
513bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
514fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
516d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
519f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
520fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
522d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
5240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
526fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
528d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
5300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
532fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
534d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
5360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
538fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
540d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
5420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
544bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
54549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
54693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
54749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
5480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
5490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
550fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
5520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
5530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
555fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
556d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
55757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
55857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
55957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
56057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
56157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
562d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
563d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
564d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
565d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
56693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
56757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
56857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
56957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
57057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
57157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
57257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
57357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
57457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
57557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
57657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
57757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
57857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
57957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
58057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
58157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
58257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
58357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
58457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
58557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
58657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
58757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
58857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
58957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
59057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
59157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
59257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
59357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
59457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
59557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
59657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
59757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
59857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
59957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
60057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
60157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
60257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
60357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
60457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
60557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
60657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
607d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
6083fb14d0868594c78a777e805545209636814e223Martijn Coenen
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
6100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
612f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
613f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
614bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
615bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
616f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
617f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
618bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
619f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
620f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
621fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
623d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
624bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
626f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
627f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
628f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
629f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
630f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
631f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
632f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
633f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
634f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
6351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
6361878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
637f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                removeSocket(nativeHandle);
6381878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
639f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
641f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
644fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
646d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
647bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
650f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
651f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
652f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
654f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
656f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
657f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
658f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
65993915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
6600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
662f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
664f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
665f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
666f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
667f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
670f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
671fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
673d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
674bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
675f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
676f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
677f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
678f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
680f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
684f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
68693915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
687f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
688f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
692f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
693f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
694f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
698fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
700d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
701bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
703f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
704f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
706f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
707f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
708f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
710f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
715f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
716f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
717f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
718fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
720d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
721bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
723f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
724f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
725f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
728f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
729f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
730f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
735f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
736f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
737f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
738fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
740d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
741bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
743f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
744f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
745f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
746f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
747f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
748f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
750f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
758fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
760d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
770f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
782fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
784d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
794f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
806fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
808d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
818f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
82028f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
82228f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
826fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
828d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
839f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
8420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
8460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
8490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
8540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
855f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
856bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
857bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
858f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
859f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
860bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
861f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
862f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
863fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
865d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
8680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
8690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
876f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
8770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
87893915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
8790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
8800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
8810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
8822f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
8831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
8841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
8851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
8862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
8870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
8880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
8890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
8900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
8920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
895fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
897d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
9000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
9040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
907f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
910f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
9110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
912f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    removeSocket(nativeHandle);
9130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
920f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
921bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
922bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
923f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
924f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
925bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
926f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
927f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
928fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
930d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
931bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
934f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
937f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
940f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9421878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
9431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
944f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                removeSocket(nativeHandle);
945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
948fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
950d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
951bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
960f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
968fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
970d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
971bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
981f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
993fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
995d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
996bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1006f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1007f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1022fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1024d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1025bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1026f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1034f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1036b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1037b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
103821545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1039b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
104249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1045f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1046fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1047ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1048d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1049bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1050f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1054f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1055f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1056f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1057f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1058f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1059b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1060b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1062ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
10631b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            if (technology == TagTechnology.NFC_B) {
10641b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen                return ErrorCodes.ERROR_NOT_SUPPORTED;
10651b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            }
10661b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen
1067ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1068ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1069ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1070ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1071ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1072ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1073ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1074ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1077fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1078aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1079aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1080aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1081f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1082aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1083aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1084aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1085aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1086aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1087aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1088aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1089f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1090aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1091aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1092aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1093aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1094aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1095aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1096aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1097aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1098aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1099aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1100aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1101b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1102d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1103bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1105f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1108f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1110f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
1111f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1112b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1113f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1114f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1117fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1119f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1120f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1123f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1126f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1127f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1128f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1129f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1131f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1134f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1136fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1137b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1138f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1139b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1140b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1141b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1142b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1143b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1144b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1145b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1146f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1147b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1148b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1149b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1150b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1151ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1152b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1153b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1154fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1156f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1165f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
11663ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
11683ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1173fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11749d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
117597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1176d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1177bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1178f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1187f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
11899d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
11909d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
11919d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
11929d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
11939d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
11949d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
11959d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1200fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12013fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1202d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1203bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1204f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1212f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1214f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                byte[] buf = tag.readNdef();
1215f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (buf == null) {
1216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1217f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                }
1218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1229fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12303fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1231d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1232bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
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 */
1241f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1242f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            if (tag.writeNdef(msg.toByteArray())) {
1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1254fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1255f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            return(mDeviceHost.doGetLastError());
1257f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1258f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1259fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
12613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1264fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
126603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
126703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
1268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
126903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
127003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
127103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
127203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
127303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
127403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
127503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
1276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
127703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
127803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
127903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
128003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
1281f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            if (tag.makeReadOnly()) {
128203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
1283f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
128403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
128503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
12880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
12890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
12900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1292f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
12930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
12950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
12960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
12970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
12980aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12990aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
1300f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
13010aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
13020aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
13030aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
13040aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13050aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
13060aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
1307f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
13080aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
13090aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
13100aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
13110aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13121b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
13133fb14d0868594c78a777e805545209636814e223Martijn Coenen        public Tag rediscover(int nativeHandle) throws RemoteException {
13143fb14d0868594c78a777e805545209636814e223Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13153fb14d0868594c78a777e805545209636814e223Martijn Coenen
1316f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
13173fb14d0868594c78a777e805545209636814e223Martijn Coenen
13183fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Check if NFC is enabled
13193fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (!mIsNfcEnabled) {
13203fb14d0868594c78a777e805545209636814e223Martijn Coenen                return null;
13213fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
13223fb14d0868594c78a777e805545209636814e223Martijn Coenen
13233fb14d0868594c78a777e805545209636814e223Martijn Coenen            /* find the tag in the hmap */
1324f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
13253fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (tag != null) {
13263fb14d0868594c78a777e805545209636814e223Martijn Coenen                // For now the prime usecase for rediscover() is to be able
13273fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to access the NDEF technology after formatting without
13283fb14d0868594c78a777e805545209636814e223Martijn Coenen                // having to remove the tag from the field, or similar
13293fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to have access to NdefFormatable in case low-level commands
13303fb14d0868594c78a777e805545209636814e223Martijn Coenen                // were used to remove NDEF. So instead of doing a full stack
13313fb14d0868594c78a777e805545209636814e223Martijn Coenen                // rediscover (which is poorly supported at the moment anyway),
13323fb14d0868594c78a777e805545209636814e223Martijn Coenen                // we simply remove these two technologies and detect them
13333fb14d0868594c78a777e805545209636814e223Martijn Coenen                // again.
13343fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF);
13353fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
1336f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                NdefMessage[] msgs = tag.findAndReadNdef();
13373fb14d0868594c78a777e805545209636814e223Martijn Coenen                // Build a new Tag object to return
13383fb14d0868594c78a777e805545209636814e223Martijn Coenen                Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
13393fb14d0868594c78a777e805545209636814e223Martijn Coenen                        tag.getTechExtras(), tag.getHandle(), mNfcTagService);
13403fb14d0868594c78a777e805545209636814e223Martijn Coenen                return newTag;
13413fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
13423fb14d0868594c78a777e805545209636814e223Martijn Coenen            return null;
13433fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
13443fb14d0868594c78a777e805545209636814e223Martijn Coenen
13451b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
1346fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen        public int setTimeout(int tech, int timeout) throws RemoteException {
13471b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1348f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            boolean success = mDeviceHost.setTimeout(tech, timeout);
1349fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            if (success) {
1350fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen                return ErrorCodes.SUCCESS;
1351fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            } else {
1352fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen                return ErrorCodes.ERROR_INVALID_PARAM;
1353fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            }
1354dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        }
1355dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1356dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        @Override
1357dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void resetTimeouts() throws RemoteException {
1358dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1359dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1360f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            mDeviceHost.resetTimeouts();
13611b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
13620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1366fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1368d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1370f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
13750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1378f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
13790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
13800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
13810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
13820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
13830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
13840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
13860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1388fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1390d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1391f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1392f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
13970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1400f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
14030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1407fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1409d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1411f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
14160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1419f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1421f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                byte[] buff = device.receive();
1422f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (buff == null) {
14230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
1424f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                }
14250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
14260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
142849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
14290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
14300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1432fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1434d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1435f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1436f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
14370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
14420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1445f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1447f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                isSuccess = device.send(data);
14480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
14500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
14510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1452f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1454f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1455fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1457d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1459f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1460f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
14640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1465f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1467f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1469f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (device.connect()) {
14700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
14710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
14720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
14740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1476fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1478d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1479f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1480f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
14810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
14860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1487f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1489f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1491f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (isSuccess = device.disconnect()) {
14920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1493b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
14940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
149549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
14960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1497f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
14980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1501f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1502fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1504d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1506f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
15070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
15080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1511f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1512f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1514f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
15170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
15180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
15190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
15200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1524fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1526d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1527f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1528f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1536f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
15390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
15410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1542f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1543fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
154497c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
154597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1546d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1548f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1549f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1553f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1554f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1556f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1558f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                return device.transceive(data);
15590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
15620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1563f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1564dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
1565dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // Blocks until a pending open() or transceive() times out.
1566dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        //TODO: This is incorrect behavior - the close should interrupt pending
1567dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // operations. However this is not supported by current hardware.
1568dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1569dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        synchronized(NfcService.this) {
1570dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (!mIsNfcEnabled) {
1571dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC adapter is disabled");
1572dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1573dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (mOpenEe == null) {
1574dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC EE closed");
1575dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1576dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
1577dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new SecurityException("Wrong PID");
1578dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1579dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1580f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            mDeviceHost.resetTimeouts();
1581dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mSecureElement.doDisconnect(mOpenEe.handle);
1582dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mOpenEe = null;
1583dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1584dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            applyRouting();
1585dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        }
1586dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    }
1587dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
158849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
158949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
159049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
159149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
159249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
159349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
159449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
159549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
159649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
159749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
159849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
159949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1601bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
160249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
160393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1604bd555ee64250126b60b24814120a2049943920caNick Pelly
160549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
160649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
160749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
160849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
160949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
161049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
161249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
161349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
161549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
161649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
161749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
161849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
161949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
162049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
162149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
162249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
16230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
162449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
162549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
162649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
162749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1628f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
1629ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
163049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
163149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
163249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
163349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
163449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
163549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
163649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
16370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1639bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
164049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
164193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
16420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
164349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
164449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
1645dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                _nfcEeClose(true, getCallingPid());
164649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
164749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
164849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
165049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
165149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1653bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
165449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
165593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1656bd555ee64250126b60b24814120a2049943920caNick Pelly
165749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
165849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
165949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
166049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
166149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
166249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
166349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
166449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
166649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
166749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
166949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
167049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
167149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
167249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
167349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
167449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
167549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
167649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
167749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
167849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
167949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
16800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
16810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
168249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
16830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1685bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
168649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
168793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
168849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
16890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1691bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
169249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
169393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
169449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
169549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
16960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
16980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
169949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
170049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
170149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
170249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
170349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
170449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
170549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
170649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1707bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
170849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
170949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
171049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
171149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
17120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
1713dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                    _nfcEeClose(false, -1);
1714dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                } catch (IOException e) { /* already closed */ }
17150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
17160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
17170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
17180bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
17190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
1720f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        boolean isSuccess = mDeviceHost.initialize();
17210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
172265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
172349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
172465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
17250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
172649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
172757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
172857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
1729ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
173057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
1731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
1732aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            Log.w(TAG, "Error enabling NFC");
17330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1734f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1735f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
1737f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1739f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1740f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1741aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    private boolean _disable(boolean oldEnabledState) {
1742aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean isSuccess;
1743aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1744aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        /* tear down the my tag server */
1745aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mNdefPushServer.stop();
1746aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1747aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // Stop watchdog if tag present
1748aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // A convenient way to stop the watchdog properly consists of
1749aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // disconnecting the tag. The polling loop shall be stopped before
1750aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // to avoid the tag being discovered again.
1751aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mIsDiscoveryOn = false;
1752aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        applyRouting();
1753aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        maybeDisconnectTarget();
1754aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1755f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        isSuccess = mDeviceHost.deinitialize();
1756aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
1757aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (isSuccess) {
1758aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mIsNfcEnabled = false;
17598586b104c1cf07c52c739c0afab0ded1bf151859Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
1760aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mNdefPushClient.setForegroundMessage(null);
1761aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1762aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1763aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        updateNfcOnSetting(oldEnabledState);
1764aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1765aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        return isSuccess;
1766aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    }
1767aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
176849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
176949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
177049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
1771275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (mScreenUnlocked) {
177249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
177349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
1774f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.doSelectSecureElement();
177549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
177649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
1777f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.doDeselectSecureElement();
1778221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
177949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
178049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
1781f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.enableDiscovery();
178249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
178349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
1784f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.disableDiscovery();
1785221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1786221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
178749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
1788f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.doDeselectSecureElement();
178949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
1790f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.disableDiscovery();
1791221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
179265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
179365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
179465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
17952436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
17962436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
17972436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
17982436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
17992436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
18002436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
1801f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (object instanceof TagEndpoint) {
1802663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
1803f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    TagEndpoint tag = (TagEndpoint) object;
18042436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
1805f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                } else if(object instanceof NfcDepEndpoint) {
1806663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
1807f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    NfcDepEndpoint device = (NfcDepEndpoint) object;
1808f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
1809663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
1810f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                        device.disconnect();
1811f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    } else {
1812663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
1813663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
1814663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
1815663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
1816663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
18172436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
18182436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
18192436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
18202436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
1821a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
1822a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
1823a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1824a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1825a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
1826a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1827a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1828a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
1829a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1830a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
1831bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1832a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
1833a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
1834a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
1835a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            executeSeReset();
1836a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
1837a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
1838a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1839a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
1840bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1841a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
1842a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
1843a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
1844a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
1845a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
1846a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1847a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1848aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1849aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean tempEnable = !mIsNfcEnabled;
1850aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
1851aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (!_enable(false)) {
1852aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                Log.w(TAG, "Could not enable NFC to reset EE!");
1853aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                return;
1854aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1855aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1856aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1857a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
1858a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
1859a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
1860a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
1861aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (tempEnable) {
1862aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                _disable(true);
1863aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1864a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1865a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1866bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1867a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
1868a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
1869bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1870a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1871a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
1872aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1873aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
1874aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            _disable(true);
1875aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1876bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
1877bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1878a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
1879a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
1880a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
1881bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1882bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
1883a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
1884a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
1885bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1886a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
1887a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
1888bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1889a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
1890a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
1891bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1892a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
1893bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1894a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
1895a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
1896bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1897bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1898a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
1899a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
1900a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
1901bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
1902a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
1903a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
1904bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
1905bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
1906a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
1907a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
1908bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
1909bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
1910bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
1911bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1912bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1913a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
1914bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
1915bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
19160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
19170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
19182f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
19190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
19202f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
19214acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
19222f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
19234acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
19242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
19252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
19262f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
192757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
192857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
192957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
193157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
193357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
193457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
193557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
193657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
193857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
193957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
194057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
194157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
194257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
194357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
194457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
194557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
194657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
194757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
194857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
194957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
195057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
195157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
195257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
195357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
195457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
195557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
195657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
195757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
195857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
195957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
196057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
196157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
196257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
196357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
196457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
196557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
196657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
196757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
196857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
196957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
197057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
197157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
197257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
197357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
197457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
197557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
19760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
19802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
198174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
198274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
1983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
1985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
1986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
1987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
1989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
1990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19922f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
1993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
1994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
1996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
1997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
1998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2003f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    synchronized void registerTagObject(TagEndpoint tag) {
2004f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mObjectMap.put(tag.getHandle(), tag);
2005b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2006b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
20072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2008b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20112f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2012bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2013bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2014bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2015bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2018f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    private void removeSocket(int key) {
2019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2022d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2023d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2024d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2025d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
20261be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
20271be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
20281be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
20291be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2030d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2031d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2032d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2033d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2034d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2035d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2036d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2037d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2038d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2039d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2040d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2041d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
20421be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
20431be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
20441be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
20451be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2046d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2047d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2048d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2049d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2050d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2051d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2052d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
20530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
20540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
20550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
20560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2057f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
20590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2060f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2061ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
20620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
20630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
206557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2066b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
206757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
206857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2069b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2070b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2071b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2072b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2073b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2074b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2075b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
20763fb14d0868594c78a777e805545209636814e223Martijn Coenen
20773fb14d0868594c78a777e805545209636814e223Martijn Coenen    final class NfcServiceHandler extends Handler {
2078232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2079b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2080b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2081f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2082b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2083b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2084b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2085b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2086b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
208757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
208857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
208976a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly               mNfcDispatcher.dispatchTag(tag, new NdefMessage[] { ndefMsg });
209057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
209157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
209257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2093f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2094ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2095f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               TagEndpoint tag = (TagEndpoint) msg.obj;
2096f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               NdefMessage[] ndefMsgs = tag.findAndReadNdef();
2097232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2098232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
2099f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   tag.startPresenceChecking();
2100f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   dispatchTagEndpoint(tag, ndefMsgs);
2101232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2102232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2103f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   if (tag.reconnect()) {
2104f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       tag.startPresenceChecking();
2105f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       dispatchTagEndpoint(tag, null);
2106232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2107232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2108f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       tag.disconnect();
2109f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2110f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2111f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
21123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2113f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2114ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2115f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
211649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
211749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
211849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
211949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
212049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
212193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2122f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2123f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2124f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2125f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
2126f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2127f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2128f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2129f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
2130ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2131f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   if (device.connect()) {
2132f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2133f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       if (mDeviceHost.doCheckLlcp()) {
2134f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2135f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                           if (mDeviceHost.doActivateLlcp()) {
2136ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2137663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2138663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2139eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2140eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2141eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2142eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2143f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                               device.disconnect();
2144b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2145b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2146f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2147ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2148f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                           device.disconnect();
2149b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2150eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
21517f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
21527f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2153f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2154f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2155f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
2156ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2157f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2158f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   if (mDeviceHost.doCheckLlcp()) {
2159f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2160f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       if (mDeviceHost.doActivateLlcp()) {
2161ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2162663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2163663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2164eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2165eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
21666f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2167ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2168f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2169b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2170f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2171f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2172f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2173f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               device = (NfcDepEndpoint) msg.obj;
2174eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2175eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2176663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2177663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2178663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2179663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2180f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
2181663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2182663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2183f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                           device.disconnect();
2184663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2185663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2186663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2187663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2188cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2189eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2190f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2191f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2192f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2193f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2194f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2195ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2196f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2197f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2198f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2199f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2200f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2201ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2202f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               Intent intent = new Intent();
2203f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
2204ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2205f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               mContext.sendOrderedBroadcast(intent, NFC_PERM);
2206f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2207f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
220857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
220957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
221057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
221157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
221257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
221357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
221457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
221557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
221657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
221757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
221857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
221957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
222057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
222157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2222c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2223c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2224c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
222549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
222693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2227c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2228c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2229c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2230c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2231c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2232c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
223349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
223493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2235c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2236c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2237c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2238f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2239f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2240f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2241f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2242b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2243d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) {
2245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
2246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
2247f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            registerTagObject(tagEndpoint);
224876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            if (!mNfcDispatcher.dispatchTag(tag, msgs)) {
2249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                unregisterObject(tagEndpoint.getHandle());
2250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                tagEndpoint.disconnect();
22513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
22523fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
2253b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2254b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2255b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
225649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
22577c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2258fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2259275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        protected Void doInBackground(Boolean... params) {
2260275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]);
2261275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2262275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (params != null && params.length > 0 && params[0]) {
2263161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2264275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (!mScreenUnlocked) {
2265275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = true;
2266275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2267275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2268275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring enable request");
2269275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2270161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
22717c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2272533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2273161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2274275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (mScreenUnlocked) {
2275275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = false;
2276275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2277275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        maybeDisconnectTarget();
2278275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2279275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring disable request");
2280275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2281161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2282533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
22837c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
22847c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
22857c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
22867c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
22877c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
22880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
22890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
22900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2291eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2293ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
22940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
229649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
229865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
22997c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
23007c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
23017c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
23027c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2303275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2304275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Only enable if the screen is unlocked. If the screen is locked
2305275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Intent.ACTION_USER_PRESENT will be broadcast when the screen is
2306275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // unlocked.
2307275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                boolean enable = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
2308275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2309275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(enable);
231065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
23117c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
23127c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
23137c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
23147c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2315275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.FALSE);
2316275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
2317275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // The user has unlocked the screen. Enabled!
2318275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
2319bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2320a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
2321bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
23227a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
23237a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
23247a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
23257a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
23267a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
23277a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
23287a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
2329a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                        if (packageName.equals(mSePackageName)) {
2330a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
23317a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
2332bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2333bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
233774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2338