NfcService.java revision d2d5dddf17ac2008547172cd72faa034a89d569b
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;
2481c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpConnectionlessSocket;
2581c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpServiceSocket;
2681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeLlcpSocket;
2781c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcManager;
2881c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcSecureElement;
298afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R;
30d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
312f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
32275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager;
3305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
41d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager;
42d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool;
433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
492094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5149d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
52f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
5924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
609d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
61aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef;
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
73bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
7457d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
7557d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7657d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
7724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
783ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
7984e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet;
802436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
81bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
823ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
83d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamiltoninterface P2pStatusListener {
84d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    void onP2pBegin();
85d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    void onP2pEnd();
86d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    void onP2pError();
87d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton}
88d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton
89d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamiltonpublic class NfcService extends Application implements DeviceHostListener, P2pStatusListener {
90bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
91bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
928d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson    static final boolean DBG = true;
9376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    static final String TAG = "NfcService";
94fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
95a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
97d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
98fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
99bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
100bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
101bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
102bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
103a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
10493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
105bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
106225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen    /*package*/ static final String PREF = "NfcServicePrefs";
107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
110d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen    private static final String PREF_ZEROCLICK_ON = "zeroclick_on";
111d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen    private static final boolean ZEROCLICK_ON_DEFAULT = true;
112f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
113a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
114a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
115b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
116b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
120b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
121c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
122c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
1232c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    static final int MSG_SE_APDU_RECEIVED = 10;
1242c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    static final int MSG_SE_EMV_CARD_REMOVAL = 11;
1252c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    static final int MSG_SE_MIFARE_ACCESS = 12;
126b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
12749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
1317efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly
13249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
13349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
13449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
13549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
13649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
13749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
13849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
13949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
1402c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    public static final String ACTION_APDU_RECEIVED =
1412c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas        "com.android.nfc_extras.action.APDU_RECEIVED";
1422c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    public static final String EXTRA_APDU_BYTES =
1432c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas        "com.android.nfc_extras.extra.APDU_BYTES";
1442c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
1452c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    public static final String ACTION_EMV_CARD_REMOVAL =
1462c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas        "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
1472c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
1482c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    public static final String ACTION_MIFARE_ACCESS_DETECTED =
1492c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas        "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
1502c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas    public static final String EXTRA_MIFARE_BLOCK =
1512c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas        "com.android.nfc_extras.extra.MIFARE_BLOCK";
1522c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
15374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
15474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
15674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
15749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
158d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen    private boolean mZeroClickOn = false;
15949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
16049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
16149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
1620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
16349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
16449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
1650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
166d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    // fields below must be used only on the UI thread and therefore aren't synchronized
167d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    boolean mP2pStarted = false;
168d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton
1692f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
1702f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
1712f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
172275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private boolean mScreenUnlocked;
17384e1e0adc2516afd35ebab029a52e764e0490559Jason parks    private HashSet<String> mSePackages = new HashSet<String>();
1742f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
1752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
17605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
177f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    private NativeNfcManager mDeviceHost;
1780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
1790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
180533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
1812ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson    NdefP2pManager mP2pManager;
182d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    int mStartSound;
183d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    int mEndSound;
184d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    int mErrorSound;
185d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    SoundPool mSoundPool; // playback synchronized on this
1862ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson
18776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    private NfcDispatcher mNfcDispatcher;
188275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private KeyguardManager mKeyguard;
189d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
190d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
191d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
19293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
19393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
19493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
19593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
19693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
19793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
19893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
19993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
20093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
20193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
20293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
20393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
20493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
205d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
206d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
207d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
210f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteEndpointDiscovered(TagEndpoint tag) {
211f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_NDEF_TAG, tag);
212f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
213f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
214f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
215f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies transaction
216f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
217d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    @Override
218f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onCardEmulationDeselected() {
219f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_TARGET_DESELECTED, null);
220f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
221f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
222f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
223f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies transaction
224f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
225d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    @Override
226f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onCardEmulationAidSelected(byte[] aid) {
227f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_CARD_EMULATION, aid);
228f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
229f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
230f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
231f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies P2P Device detected, to activate LLCP link
232f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    @Override
234f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onLlcpLinkActivated(NfcDepEndpoint device) {
235f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
236f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
237f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    /**
239f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     * Notifies P2P Device detected, to activate LLCP link
240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton     */
241d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    @Override
242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
246d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    @Override
247f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteFieldActivated() {
248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null);
249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
251d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    @Override
252f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    public void onRemoteFieldDeactivated() {
253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null);
254f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    }
255f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton
256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    @Override
257442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    public void onSeApduReceived(byte[] apdu) {
258442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly        sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
259442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    }
260442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly
261442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    @Override
262442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    public void onSeEmvCardRemoval() {
263442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly        sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null);
264442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    }
265442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly
266442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    @Override
267442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    public void onSeMifareAccess(byte[] block) {
268442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly        sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
269442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    }
270442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly
271442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly    @Override
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
2732f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
2742f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
2752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
2762f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
277d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
278d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
279d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
280d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        mStartSound = mSoundPool.load(this, R.raw.start, 1);
281d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        mEndSound = mSoundPool.load(this, R.raw.end, 1);
282d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        mErrorSound = mSoundPool.load(this, R.raw.error, 1);
283d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton
2840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
285f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mDeviceHost = new NativeNfcManager(this, this);
286f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mDeviceHost.initializeNativeStructure();
28774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
288d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        mP2pManager = new NdefP2pManager(this, this);
2892ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        mNfcDispatcher = new NfcDispatcher(this, mP2pManager);
29024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
2910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
292eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai        mEeRoutingState = ROUTE_OFF;
2930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
294275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
296f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2977efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly        mIsNfcEnabled = false;  // load from preferences later
298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
299275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
300275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
301533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
302275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
303275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
304533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
305d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
307eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
30865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
30965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
310bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
311275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        filter.addAction(Intent.ACTION_USER_PRESENT);
312275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
313bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
314bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
315bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
316bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
317bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
318275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
3190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
3210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
3220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
3230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
3240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
325e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly                    _enable(false, true);
326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
327a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
3310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
333d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    private void playSound(int sound) {
334d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        synchronized (this) {
335d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            mSoundPool.play(sound, 1.0f, 1.0f, 0, 0, 1.0f);
336d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        }
337d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton    }
338d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton
3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
340d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    public void onP2pBegin() {
341d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        if (!mP2pStarted) {
342d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            playSound(mStartSound);
343d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            mP2pStarted = true;
344d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        }
345d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    }
346d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton
347d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    @Override
348d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    public void onP2pEnd() {
349d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        if (mP2pStarted) {
350d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            playSound(mEndSound);
351d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            mP2pStarted = false;
352d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        }
353d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    }
354d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton
355d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    @Override
356d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    public void onP2pError() {
357d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        if (mP2pStarted) {
358d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            playSound(mErrorSound);
359d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton            mP2pStarted = false;
360d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton        }
361d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    }
362d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton
363d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton    @Override
3642f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
3652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
3662f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
3670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
3690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
3713ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
3723ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
3734acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
374fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
37693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
3790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
3800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
3810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
382e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly                isSuccess = _enable(previouslyEnabled, true);
383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
387fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
3890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
39093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
3910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
392ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
3930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
395e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly                isSuccess = _disable(previouslyEnabled, true);
396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
400fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
401d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        public boolean zeroClickEnabled() throws RemoteException {
402d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            return mZeroClickOn;
403d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        }
404d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen
405d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        @Override
406d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        public boolean enableZeroClick() throws RemoteException {
407d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            NfcService.enforceAdminPerm(mContext);
408d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            synchronized(NfcService.this) {
409d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                if (!mZeroClickOn) {
410d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    Log.e(TAG, "ENABLING 0-CLICK");
411d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, true);
412d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mPrefsEditor.apply();
413d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mP2pManager.enableNdefServer();
414d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mZeroClickOn = true;
415d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                }
416d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            }
417d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            return true;
418d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        }
419d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen
420d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        @Override
421d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        public boolean disableZeroClick() throws RemoteException {
422d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            NfcService.enforceAdminPerm(mContext);
423d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            synchronized(NfcService.this) {
424d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                if (mZeroClickOn) {
425d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    Log.e(TAG, "DISABLING 0-CLICK");
426d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, false);
427d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mPrefsEditor.apply();
428d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mP2pManager.disableNdefServer();
429d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                    mZeroClickOn = false;
430d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                }
431d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            }
432d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            return true;
433d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        }
434d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen
435d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen
436d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        @Override
43705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
43824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
439a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
44005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
441a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
442a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
443a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
444ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
445ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
446a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
447a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
448a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
449a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
450a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
451a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
452a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
453a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
454a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
455a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
456a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
457a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
458a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
459a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
46024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
46124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
46224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
46324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
46424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
46549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
46676a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists);
46705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
46805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
46905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
47005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
47105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
47276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly
47376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
47405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
47505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
47605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
477ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
478ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
479ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
480ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
481ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
4822ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (mP2pManager.setForegroundMessage(msg)) {
483ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
484ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
485ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
486ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
487ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
4882094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
4892094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
4902094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4912094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
4922094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
4932094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
4942ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            if (mP2pManager.setForegroundCallback(callback)) {
4952094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
4962094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
4972094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
4982094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
4992094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
500ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
501ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5022ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            boolean hadMsg = mP2pManager.setForegroundMessage(null);
5032ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            boolean hadCallback = mP2pManager.setForegroundCallback(null);
5042094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
505ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
506ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
507ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
508ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
509ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
5100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
511d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
512bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
514f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
517f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
5190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
5211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
5221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
524f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpConnectionlessSocket(sap);
5251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5301878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5311878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
5321878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
533f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
534f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5351878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
536f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
5371878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5381878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5391878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5401878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5411878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5421878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5451878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
547f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
548f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
549fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
5510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
552d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
553bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
554f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
555f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
556f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
557f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
5600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
561f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
5621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
5631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
5641878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
5651878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
5660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
5681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
569f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    return mGeneratedSocketHandle;
570f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
5721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
573f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
5741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
5751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
5761878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
5771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
5781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
5791878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
5801878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
5811878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
5821878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
585f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
586fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
589d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
590bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
591f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
593f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
5961878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
5971878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
598bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
599f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            socket = mDeviceHost.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
6021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
6031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
6041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
6050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
6071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
6081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
6090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
610f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
612f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                int errorStatus = mDeviceHost.doGetLastError();
6131878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6141878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
6151878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
6161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
6171878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
6181878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
6191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
6201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
6211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
6221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
6231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
626f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
627fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
629d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
632bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
633fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
635d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
638f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
639fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
641d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
644f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
645fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
647d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
651fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
653d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
6550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
657fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
659d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
6600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
663bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
66449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
66593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
66649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
6670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
6680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
669fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
6710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
6720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
6730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
6740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
676f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
677f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
678bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
679bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
680f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
681f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
682bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
683f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
684f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
685fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
687d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
688bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
692f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
693f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
694f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
695f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
697f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
698f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
6991878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
7001878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
701f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                removeSocket(nativeHandle);
7021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
703f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
706f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
707f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
708fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
710d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
711bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
712f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
7130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
715f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
716f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
717f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
718f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
719f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
720f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
721f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
722f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
72393915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
726f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
728f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
729f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
730f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
731f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
733f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
734f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
735fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
737d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
738bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
739f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
740f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
741f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
742f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
743f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
744f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
745f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
746f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
747f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
748f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
749f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
75093915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
751f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
752f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
753f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
754f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
755f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
756f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
757f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
758f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
760f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
761f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
762fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
764d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
765bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
767f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
768f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
769f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
770f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
771f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
772f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
774f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
777f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
779f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
780f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
781f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
782fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
784d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
785bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
787f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
788f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
789f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
791f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
792f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
793f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
794f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
795f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
799f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
800f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
801f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
802fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
804d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
805bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
807f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
808f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
811f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
812f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
813f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
814f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
822fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
824d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
834f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
846fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
848d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
858f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
8610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
8620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
8670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
870fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
872d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
882f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
88428f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
8850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
88628f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
8870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
890fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
892d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
8950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
8960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
903f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
9060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
9070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
9080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
9090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
9100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
9120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
9130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
9160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
9180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
919f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
920bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
921bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
922f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
923f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
924bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
925f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
926f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
927fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
929d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
9320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
9330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
9370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
940f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
9410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
94293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
9430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
9440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
9450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
9462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
9471878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
9481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
9491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
9502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
9510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
9520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
9530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
9540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
9550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
9560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
9580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
959fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
9600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
961d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
9620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
9640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
9660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
9670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
9680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
9700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
971f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
9720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
9731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
974f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
9750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
976f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    removeSocket(nativeHandle);
9770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
9780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
9790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
984f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
985bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
986bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
987f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
988f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
989bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
990f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
991f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
992fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
994d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
995bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1004f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
10061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
10071878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
1008f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                removeSocket(nativeHandle);
1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1012fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
1014d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1015bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1022f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1024f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1032fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
1034d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1035bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1039f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1042f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1045f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1046f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1047f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
1049f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
1050f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1054f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1055f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1056f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1057fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1058f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
1059d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1060bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
1062f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1065f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1066f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1067f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1068f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1069f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
1070f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
1071f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
1072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
1073f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
1074f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
1076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
1077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1078f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
1079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1080f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1081f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1082f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
1083f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1084f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
1085f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1086fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1087f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
1088d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1089bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1090f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1091f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1092f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1093f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1094f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1096f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1097f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1098f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1100b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1101b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
110221545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1103b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1105f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
110649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1108f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1110fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1111ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1112d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1113bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1114f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1119f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1120f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1122f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1123b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1124b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1126ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
11271b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            if (technology == TagTechnology.NFC_B) {
11281b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen                return ErrorCodes.ERROR_NOT_SUPPORTED;
11291b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            }
11301b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen
1131ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1132ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1133ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1134ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1135ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1136ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1137ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1138ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1139f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1141fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1142aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1143aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1144aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1145f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1146aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1147aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1148aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1149aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1150aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1151aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1152aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1153f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1154aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1155aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1156aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1157aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1158aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1159aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1160aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1161aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1162aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1163aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1164aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1165b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1166d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1167bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1174f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
1175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1176b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1181fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1183f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1192f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1200fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1201b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1202f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1203b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1204b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1205b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1206b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1207b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1208b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1209b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1210f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1212b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1213b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1214b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1215ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1216b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1217b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1218fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1220f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1222f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1229f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
12303ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
12323ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1233f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1237fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12389d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
123997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1240d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1241bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1248f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1249f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
12539d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
12549d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
12559d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
12569d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
12579d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
12589d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
12599d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1263f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1264fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1266d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1267bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1272f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1274f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1278f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                byte[] buf = tag.readNdef();
1279f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (buf == null) {
1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1281f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                }
1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1289f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1290f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1291f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1292f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1293fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12943fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1295d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1296bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1297f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1301f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1303f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1304f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1305f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
1306f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1310f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            if (tag.writeNdef(msg.toByteArray())) {
1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1312f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1318fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1320f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            return(mDeviceHost.doGetLastError());
1321f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1323fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13243fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
13253fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1328fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13293fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
133003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
133103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
1332f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
133303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
133403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
133503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
133603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
133703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
133803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
133903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
1340f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
134103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
134203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
134303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
134403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
1345f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            if (tag.makeReadOnly()) {
134603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
1347f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
134803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
134903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1350f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1351f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13520aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
13530aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
13540aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13550aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
1356f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag;
13570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
13590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
13600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
13610aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
13620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
1364f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
13650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
13660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
13670aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
13680aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13690aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
13700aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
1371f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            } else {
13720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
13730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
13740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
13750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
13761b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
13773fb14d0868594c78a777e805545209636814e223Martijn Coenen        public Tag rediscover(int nativeHandle) throws RemoteException {
13783fb14d0868594c78a777e805545209636814e223Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13793fb14d0868594c78a777e805545209636814e223Martijn Coenen
1380f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            TagEndpoint tag = null;
13813fb14d0868594c78a777e805545209636814e223Martijn Coenen
13823fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Check if NFC is enabled
13833fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (!mIsNfcEnabled) {
13843fb14d0868594c78a777e805545209636814e223Martijn Coenen                return null;
13853fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
13863fb14d0868594c78a777e805545209636814e223Martijn Coenen
13873fb14d0868594c78a777e805545209636814e223Martijn Coenen            /* find the tag in the hmap */
1388f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            tag = (TagEndpoint) findObject(nativeHandle);
13893fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (tag != null) {
13903fb14d0868594c78a777e805545209636814e223Martijn Coenen                // For now the prime usecase for rediscover() is to be able
13913fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to access the NDEF technology after formatting without
13923fb14d0868594c78a777e805545209636814e223Martijn Coenen                // having to remove the tag from the field, or similar
13933fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to have access to NdefFormatable in case low-level commands
13943fb14d0868594c78a777e805545209636814e223Martijn Coenen                // were used to remove NDEF. So instead of doing a full stack
13953fb14d0868594c78a777e805545209636814e223Martijn Coenen                // rediscover (which is poorly supported at the moment anyway),
13963fb14d0868594c78a777e805545209636814e223Martijn Coenen                // we simply remove these two technologies and detect them
13973fb14d0868594c78a777e805545209636814e223Martijn Coenen                // again.
13983fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF);
13993fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
1400f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                NdefMessage[] msgs = tag.findAndReadNdef();
14013fb14d0868594c78a777e805545209636814e223Martijn Coenen                // Build a new Tag object to return
14023fb14d0868594c78a777e805545209636814e223Martijn Coenen                Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
14033fb14d0868594c78a777e805545209636814e223Martijn Coenen                        tag.getTechExtras(), tag.getHandle(), mNfcTagService);
14043fb14d0868594c78a777e805545209636814e223Martijn Coenen                return newTag;
14053fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
14063fb14d0868594c78a777e805545209636814e223Martijn Coenen            return null;
14073fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
14083fb14d0868594c78a777e805545209636814e223Martijn Coenen
14091b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
1410fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen        public int setTimeout(int tech, int timeout) throws RemoteException {
14111b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1412f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            boolean success = mDeviceHost.setTimeout(tech, timeout);
1413fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            if (success) {
1414fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen                return ErrorCodes.SUCCESS;
1415fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            } else {
1416fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen                return ErrorCodes.ERROR_INVALID_PARAM;
1417fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen            }
1418dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        }
1419dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1420dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        @Override
1421358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen        public int getTimeout(int tech) throws RemoteException {
1422358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1423358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen
1424358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen            return mDeviceHost.getTimeout(tech);
1425358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen        }
1426358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen
1427358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen        @Override
1428dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void resetTimeouts() throws RemoteException {
1429dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1430dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1431f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            mDeviceHost.resetTimeouts();
14321b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
14330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1434f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1437fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1439d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1441f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
14460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1449f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
14520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
14530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
14540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
14550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
14570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1459fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1461d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1463f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1464f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
14680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1471f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
14740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1475f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1477f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1478fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1480d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1482f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
14870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1488f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1490f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
14910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1492f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                byte[] buff = device.receive();
1493f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (buff == null) {
14940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
1495f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                }
14960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
14970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
149949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
15000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1502f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1503fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1505d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1506f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1507f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
15080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1509f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
15130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1514f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1516f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1518f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                isSuccess = device.send(data);
15190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
15210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
15220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1526fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1528d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1529f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1530f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1531f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
15350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1538f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1540f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (device.connect()) {
15410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
15420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
15430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
15450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1546f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1547fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1549d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1550f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1551f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
15520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1553f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
15570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1558f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1560f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1562f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (isSuccess = device.disconnect()) {
15630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1564b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
15650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
156649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
15670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
15690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1570f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1573fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1575d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1576f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1577f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
15780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
15790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1585f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
15860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
15880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
15890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
15900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
15910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1595fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
15960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1597d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1599f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1604f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1605f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1607f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
16080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
16090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
16100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
16120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1613f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1614fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
161597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
161697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1617d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1618f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1619f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            NfcDepEndpoint device;
1620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
16220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
16230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1625f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
16260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
1627f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            device = (NfcDepEndpoint) findObject(nativeHandle);
16280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
1629f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                return device.transceive(data);
16300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
16310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
16320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
16330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1634f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1635dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
1636dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // Blocks until a pending open() or transceive() times out.
1637dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        //TODO: This is incorrect behavior - the close should interrupt pending
1638dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // operations. However this is not supported by current hardware.
1639dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1640dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        synchronized(NfcService.this) {
1641dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (!mIsNfcEnabled) {
1642dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC adapter is disabled");
1643dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1644dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (mOpenEe == null) {
1645dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC EE closed");
1646dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1647dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
1648dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new SecurityException("Wrong PID");
1649dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1650dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1651f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            mDeviceHost.resetTimeouts();
1652dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mSecureElement.doDisconnect(mOpenEe.handle);
1653dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mOpenEe = null;
1654dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1655dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            applyRouting();
1656dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        }
1657dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    }
1658dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
165949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
166049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
166149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
166249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
166349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
166449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
166549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
166649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
166749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
166849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
166949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
167049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1672bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
167349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
167493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1675bd555ee64250126b60b24814120a2049943920caNick Pelly
167649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
167749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
167849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
167949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
168049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
168149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
168349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
168449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
168649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
168749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
168849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
168949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
169049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
169149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
169249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
169349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
16940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
169549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
169649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
169749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
169849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1699f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
1700ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
170149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
170249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
170349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
170449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
170549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
170649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
170784e1e0adc2516afd35ebab029a52e764e0490559Jason parks
170884e1e0adc2516afd35ebab029a52e764e0490559Jason parks                // Add the calling package to the list of packages that have accessed
170984e1e0adc2516afd35ebab029a52e764e0490559Jason parks                // the secure element.
171084e1e0adc2516afd35ebab029a52e764e0490559Jason parks                for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) {
171184e1e0adc2516afd35ebab029a52e764e0490559Jason parks                    mSePackages.add(packageName);
171284e1e0adc2516afd35ebab029a52e764e0490559Jason parks                }
171349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
17140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
17150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1716bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
171749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
171893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
17190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
172049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
172149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
1722dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                _nfcEeClose(true, getCallingPid());
172349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
172449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
172549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
17260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
172749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
172849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
17290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1730bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
173149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
173293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1733bd555ee64250126b60b24814120a2049943920caNick Pelly
173449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
173549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
173649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
173749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
173849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
173949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
174049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
174149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
17420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
174349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
174449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
17450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
174649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
174749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
174849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
174949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
175049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
175149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
175249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
175349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
175449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
175549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
175649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
17570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
17580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
175949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
17600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
17610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1762bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
176349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
176493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
176549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
17660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
17670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1768bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
176949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
177093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
177149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
177249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
17730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
1774bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1775bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
17765a8844da9bc569aa7289426bf7b96e7eef90abf5Nick Pelly        public void authenticate(byte[] token) throws RemoteException {
1777bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            NfcService.enforceNfceeAdminPerm(mContext);
1778bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
17790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
17800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
178149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
178249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
178349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
178449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
178549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
178649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
178749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
178849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1789bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
179049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
179149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
179249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
179349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
17940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
1795dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                    _nfcEeClose(false, -1);
1796dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                } catch (IOException e) { /* already closed */ }
17970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
17980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
17990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
18000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1801e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly    private boolean _enable(boolean oldEnabledState, boolean savePref) {
1802f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        boolean isSuccess = mDeviceHost.initialize();
18030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
180465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
180549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
180665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
18070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
180849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1809e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen            synchronized(NfcService.this) {
1810e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                boolean zeroclick_on = mPrefs.getBoolean(PREF_ZEROCLICK_ON,
1811e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                        ZEROCLICK_ON_DEFAULT);
1812e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                if (zeroclick_on) {
1813e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                    /* bring up p2p ndef servers */
1814e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                    mP2pManager.enableNdefServer();
1815e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                    mZeroClickOn = true;
1816e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                }
1817d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen            }
1818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
1819aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            Log.w(TAG, "Error enabling NFC");
18200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1821f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1822f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1823e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly        if (savePref) {
1824e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly            updateNfcOnSetting(oldEnabledState);
1825e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly        }
1826f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
18270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1828f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1830e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly    private boolean _disable(boolean oldEnabledState, boolean savePref) {
18312083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly        /* sometimes mDeviceHost.deinitialize() hangs, watch-dog it */
18322edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        WatchDogThread watchDog = new WatchDogThread();
18332edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        watchDog.start();
18342edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly
1835aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean isSuccess;
1836aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
18372ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson        /* tear down the p2p server */
1838e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen        synchronized(NfcService.this) {
1839e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen            if (mZeroClickOn) {
1840e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                mP2pManager.disableNdefServer();
1841e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen                mZeroClickOn = false;
1842e063132e40dc788f0b471ed3832f5fbaebd7e463Martijn Coenen            }
1843d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen        }
1844aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // Stop watchdog if tag present
1845aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // A convenient way to stop the watchdog properly consists of
1846aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // disconnecting the tag. The polling loop shall be stopped before
1847aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // to avoid the tag being discovered again.
1848aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mIsDiscoveryOn = false;
1849aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        applyRouting();
1850aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        maybeDisconnectTarget();
1851aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1852f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        isSuccess = mDeviceHost.deinitialize();
1853aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
1854aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (isSuccess) {
1855aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mIsNfcEnabled = false;
18568586b104c1cf07c52c739c0afab0ded1bf151859Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
18572ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson            mP2pManager.setForegroundMessage(null);
1858aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1859aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1860e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly        if (savePref) {
1861e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly            updateNfcOnSetting(oldEnabledState);
1862e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly        }
1863aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
18642edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        watchDog.cancel();
1865aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        return isSuccess;
1866aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    }
1867aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
18682edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly    private class WatchDogThread extends Thread {
18692edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        boolean mWatchDogCanceled = false;
18702edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        @Override
18712edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        public void run() {
18722edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            boolean slept = false;
18732edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            while (!slept) {
18742edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                try {
18752edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    Thread.sleep(10000);
18762edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    slept = true;
18772edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                } catch (InterruptedException e) { }
18782edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            }
18792edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            synchronized (this) {
18802edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                if (!mWatchDogCanceled) {
18812edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    // Trigger watch-dog
18822edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                    Log.e(TAG, "Watch dog triggered");
18832083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly                    mDeviceHost.doAbort();
18842edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly                }
18852edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            }
18862edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        }
18872edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        public synchronized void cancel() {
18882edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            mWatchDogCanceled = true;
18892edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly        }
18902edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly    }
18912edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly
189249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
189349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
189449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
1895275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (mScreenUnlocked) {
189649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
189749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
1898f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.doSelectSecureElement();
189949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
190049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
1901f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.doDeselectSecureElement();
1902221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
190349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
190449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
1905f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.enableDiscovery();
190649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
190749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
1908f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    mDeviceHost.disableDiscovery();
1909221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1910221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
191149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
1912f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.doDeselectSecureElement();
191349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
1914f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                mDeviceHost.disableDiscovery();
1915221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
191665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
191765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
191865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
19192436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
19202436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
19212436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
19222436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
19232436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
19242436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
1925f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                if (object instanceof TagEndpoint) {
1926663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
1927f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    TagEndpoint tag = (TagEndpoint) object;
19282436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
1929f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                } else if(object instanceof NfcDepEndpoint) {
1930663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
1931f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    NfcDepEndpoint device = (NfcDepEndpoint) object;
1932f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
1933663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
1934f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                        device.disconnect();
1935f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    } else {
1936663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
1937663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
1938663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
1939663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
1940663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
19412436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
19422436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
19432436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
19442436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
1945a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
1946a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
1947a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1948a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1949a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
1950a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1951a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1952a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
1953a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1954a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
1955bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1956a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
1957a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
1958a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
1959a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
1960a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
19612edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly            executeSeReset();
1962a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1963a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
1964bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1965a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
1966a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
1967a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
1968a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
1969a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
1970a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1971a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1972aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1973aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean tempEnable = !mIsNfcEnabled;
1974aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
1975e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly            if (!_enable(false, false)) {
1976aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                Log.w(TAG, "Could not enable NFC to reset EE!");
1977aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                return;
1978aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1979aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1980aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1981a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
1982a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
1983a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
1984a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
1985aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (tempEnable) {
1986e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly                _disable(true, false);
1987aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1988a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1989a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1990bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1991ce77cf9b062cc749f488994cefd958e23994d60eNick Pelly        mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
199285a8366a75041491a22928f65357c69d112c9925Daniel Tomas
1993a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
1994a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
1995bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1996a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1997ce77cf9b062cc749f488994cefd958e23994d60eNick Pelly        mDeviceHost.resetTimeouts();
199885a8366a75041491a22928f65357c69d112c9925Daniel Tomas
1999a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
2000aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
2001aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
2002e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly            _disable(true, false);
2003aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
2004bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2005bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2006a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
2007a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
2008a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
2009bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2010bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
2011a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
2012a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
2013bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2014a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
2015a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
2016bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2017a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
2018a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
2019bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2020a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
2021bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2022a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
2023a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
2024bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2025bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
2026a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
2027a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
2028a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
2029bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
2030a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
2031a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
2032bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
2033bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
2034a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
2035a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
2036bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2037bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
2038bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
2039bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
2040bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
2041a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
2042bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
2043bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
20440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
20450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
20462f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
20470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
20482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
20494acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
20502f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
20514acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
20522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
20532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
20542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
20550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
2056f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2057f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2058f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
20592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
206074180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
206174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
2062f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
2064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
2065f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
2066f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2067f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
2068f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
2069f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2070f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20712f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
2072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
2073f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2074f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
2075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
2076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
2077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2078f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
2080f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2081f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2082f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    synchronized void registerTagObject(TagEndpoint tag) {
2083f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        mObjectMap.put(tag.getHandle(), tag);
2084b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2085b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
20862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
2087b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
2088f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2089f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
2091bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
2092bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
2093bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
2094bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
2095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2096f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2097f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton    private void removeSocket(int key) {
2098f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
2099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
2100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2101d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2102d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2103d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2104d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
21051be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
21061be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
21071be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
21081be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2109d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2110d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2111d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2112d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2113d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2114d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2115d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2116d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2117d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2118d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2119d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2120d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
21211be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
21221be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
21231be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
21241be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2125d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2126d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2127d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2128d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2129d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2130d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2131d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
213257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2133b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
213457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
213557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
21368d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson    public void sendMeProfile(NdefMessage target, NdefMessage profile) {
21378d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson        mP2pManager.sendMeProfile(target, profile);
21388d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson    }
21398d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson
2140b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2141b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2142b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2143b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2144b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2145b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2146b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
21473fb14d0868594c78a777e805545209636814e223Martijn Coenen    final class NfcServiceHandler extends Handler {
2148232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2149b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2150b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2151f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2152b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2153b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2154aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton               Bundle extras = new Bundle();
2155aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton               extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
2156aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton               extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
2157aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton               extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
2158aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton               extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
2159b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2160aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton                       new int[] { TagTechnology.NDEF },
2161aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamilton                       new Bundle[] { extras });
216257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
216357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
2164d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton               boolean delivered = mNfcDispatcher.dispatchTag(tag, new NdefMessage[] { ndefMsg });
2165d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton               if (delivered) {
2166d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton                   onP2pEnd();
2167d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton               }
216857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
216957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
217057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2171f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2172ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2173f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               TagEndpoint tag = (TagEndpoint) msg.obj;
2174d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton               playSound(mStartSound);
2175f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               NdefMessage[] ndefMsgs = tag.findAndReadNdef();
2176232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2177232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
2178f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   tag.startPresenceChecking();
2179f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   dispatchTagEndpoint(tag, ndefMsgs);
2180232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2181232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2182f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                   if (tag.reconnect()) {
2183f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       tag.startPresenceChecking();
2184f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       dispatchTagEndpoint(tag, null);
2185232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2186232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2187f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       tag.disconnect();
2188d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton                       playSound(mErrorSound);
2189f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2190f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2191f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
21923fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2193f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2194ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2195f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
219649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
219749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
219849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
219949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
22002c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED);
220193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2202f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2203f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
22042c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas           case MSG_SE_EMV_CARD_REMOVAL:
22052c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "Card Removal message");
22062c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               /* Send broadcast */
22072c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               Intent cardRemovalIntent = new Intent();
22082c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL);
22092c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL);
22102c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               mContext.sendBroadcast(cardRemovalIntent, NFCEE_ADMIN_PERM);
22112c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               break;
22122c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
22132c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas           case MSG_SE_APDU_RECEIVED:
22142c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "APDU Received message");
22152c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               byte[] apduBytes = (byte[]) msg.obj;
22162c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               /* Send broadcast */
22172c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               Intent apduReceivedIntent = new Intent();
22182c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               apduReceivedIntent.setAction(ACTION_APDU_RECEIVED);
22192c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (apduBytes != null && apduBytes.length > 0) {
22202c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas                 apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes);
22212c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               }
22222c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED);
22232c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               mContext.sendBroadcast(apduReceivedIntent, NFCEE_ADMIN_PERM);
22242c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               break;
22252c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
22262c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas           case MSG_SE_MIFARE_ACCESS:
22272c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "MIFARE access message");
22282c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               /* Send broadcast */
22292c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               byte[] mifareCmd = (byte[]) msg.obj;
22302c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               Intent mifareAccessIntent = new Intent();
22312c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED);
22322c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (mifareCmd != null && mifareCmd.length > 1) {
22332c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas                 int mifareBlock = mifareCmd[1] & 0xff;
22342c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas                 if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock);
22352c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas                 mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock);
22362c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               }
22372c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED);
22382c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               mContext.sendBroadcast(mifareAccessIntent, NFCEE_ADMIN_PERM);
22392c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas               break;
22402c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas
2241f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2242d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton               llcpActivated((NfcDepEndpoint) msg.obj);
2243f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2244f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2245f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2246d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton               NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
2247eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2248eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2249663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2250663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2251663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2252663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                       if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
2254663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2255663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                           device.disconnect();
2257663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2258663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2259663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2260663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2261cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2262eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
22632ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson               mP2pManager.llcpDeactivated();
2264f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2265f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2266f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2267f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2268ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               Intent intent = new Intent();
2270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
2271ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton               mContext.sendOrderedBroadcast(intent, NFC_PERM);
2273f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2274f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2275c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2276c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2277c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
227849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
227993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2280c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2281c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2282c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2283c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2284c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2285c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
228649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
228793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2288c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2289c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2290c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2291f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2292f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2293f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2294f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2295b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2296d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2297d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        private boolean llcpActivated(NfcDepEndpoint device) {
2298d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            Log.d(TAG, "LLCP Activation message");
2299d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton
2300d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
2301d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2302d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                if (device.connect()) {
2303d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    /* Check LLCP compliancy */
2304d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    if (mDeviceHost.doCheckLlcp()) {
2305d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        /* Activate LLCP Link */
2306d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        if (mDeviceHost.doActivateLlcp()) {
2307d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2308d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            // Register P2P device
2309d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            mObjectMap.put(device.getHandle(), device);
2310d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                            // TODO this should be done decently instead, not depend on the bool
2311d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                            if (mZeroClickOn) {
2312d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                                mP2pManager.llcpActivated();
2313d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                            }
2314d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            return true;
2315d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        } else {
2316d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            /* should not happen */
2317d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
2318d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                            device.disconnect();
2319d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        }
2320d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    } else {
2321d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2322d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        device.disconnect();
2323d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    }
2324d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                } else {
2325d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
2326d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    /*
2327d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                     * The polling loop should have been restarted in failing
2328d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                     * doConnect
2329d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                     */
2330d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                }
2331d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
2332d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2333d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                /* Check LLCP compliancy */
2334d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                if (mDeviceHost.doCheckLlcp()) {
2335d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    /* Activate LLCP Link */
2336d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    if (mDeviceHost.doActivateLlcp()) {
2337d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2338d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        // Register P2P device
2339d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        mObjectMap.put(device.getHandle(), device);
2340d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                        // TODO this should be done decently instead, not depend on the bool
2341d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                        if (mZeroClickOn) {
2342d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                            mP2pManager.llcpActivated();
2343d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen                        }
2344d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                        return true;
2345d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    }
2346d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                } else {
2347d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                    Log.w(TAG, "checkLlcp failed");
2348d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                }
2349d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            }
2350d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton
2351d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            return false;
2352d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton        }
2353d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton
2354f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton        private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) {
2355f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
2356f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                    tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
2357f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton            registerTagObject(tagEndpoint);
235876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            if (!mNfcDispatcher.dispatchTag(tag, msgs)) {
2359f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton                unregisterObject(tagEndpoint.getHandle());
2360d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                playSound(mErrorSound);
2361d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton            } else {
2362d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton                playSound(mEndSound);
23633fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
23643fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
2365b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2366b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2367b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
236849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
23697c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2370fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2371275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        protected Void doInBackground(Boolean... params) {
2372275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]);
2373275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2374275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (params != null && params.length > 0 && params[0]) {
2375161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2376275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (!mScreenUnlocked) {
2377275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = true;
2378275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2379275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2380275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring enable request");
2381275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2382161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
23837c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2384533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2385161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2386275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (mScreenUnlocked) {
2387275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = false;
2388275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2389275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        maybeDisconnectTarget();
2390275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2391275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring disable request");
2392275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2393161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2394533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
23957c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
23967c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
23977c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
23987c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
23997c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
24000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
24010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
24020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2403eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2405ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
24060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
240849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
241065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
2411275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Only enable if the screen is unlocked. If the screen is locked
2412275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Intent.ACTION_USER_PRESENT will be broadcast when the screen is
2413275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // unlocked.
24146ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly                boolean enable = !mKeyguard.isKeyguardSecure() || !mKeyguard.isKeyguardLocked();
2415275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
24166ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly                // Perform discovery enable in thread to protect against ANR when the
24176ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
24186ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly                // configuration of the local NFC adapter should be very quick and should
24196ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2420275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(enable);
242165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
24227c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
24237c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
24247c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
24257c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2426275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.FALSE);
2427275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
2428275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // The user has unlocked the screen. Enabled!
2429275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
2430bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2431a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
2432bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
24337a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
24347a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
24357a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
24367a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
24377a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
24387a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
24397a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
244084e1e0adc2516afd35ebab029a52e764e0490559Jason parks                        if (mSePackages.contains(packageName)) {
2441a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
244284e1e0adc2516afd35ebab029a52e764e0490559Jason parks                            mSePackages.remove(packageName);
24437a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
2444bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2445bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2448f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
244974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2450