NfcService.java revision 7efbf69a37134ccbd86a1f6b4121f16b4a80eaae
1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/*
2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License.
6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at
7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly *
10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software
11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and
14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License.
15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */
16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellypackage com.android.nfc;
18f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpServiceSocket;
20d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamiltonimport com.android.internal.nfc.LlcpSocket;
2124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport com.android.nfc.RegisteredComponentCache.ComponentInfo;
22ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushClient;
23ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamiltonimport com.android.nfc.ndefpush.NdefPushServer;
248afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R;
25d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.Activity;
271a9eca5f84036d7dd3e28000290caa2f641856deNick Pellyimport android.app.ActivityManagerNative;
282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application;
2924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.app.IActivityManager;
30275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager;
3105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent;
3293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.app.PendingIntent.CanceledException;
33bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.app.StatusBarManager;
34b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.content.ActivityNotFoundException;
3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver;
3605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName;
3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context;
3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent;
3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter;
400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences;
4193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager;
4224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.content.pm.ResolveInfo;
433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri;
44bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport android.nfc.ApduList;
45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes;
46f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException;
47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpConnectionlessSocket;
48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpServiceSocket;
49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ILlcpSocket;
502094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback;
510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter;
5249d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras;
53f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag;
54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pInitiator;
55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.IP2pTarget;
56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.LlcpPacket;
57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage;
583fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.nfc.NdefRecord;
59f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter;
600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag;
613fb14d0868594c78a777e805545209636814e223Martijn Coenenimport android.nfc.tech.TagTechnology;
6224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel;
639d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult;
647c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask;
65b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle;
66b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler;
6749d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder;
68b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message;
69533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager;
70f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException;
7113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager;
72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log;
73f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
7457d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.ByteArrayOutputStream;
75bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataInputStream;
76bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.io.DataOutputStream;
7757d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileInputStream;
7857d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileNotFoundException;
7957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.FileOutputStream;
8057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException;
813fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.nio.charset.Charsets;
8224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport java.util.ArrayList;
833fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport java.util.Arrays;
843ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap;
852436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Feririmport java.util.Iterator;
86bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parksimport java.util.List;
873ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton
882f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellypublic class NfcService extends Application {
89bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
90bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
91ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton    static final boolean DBG = false;
9276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    static final String TAG = "NfcService";
93fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
9457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    private static final String MY_TAG_FILE_NAME = "mytag";
95a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
9657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
9713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    static {
9813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly        System.loadLibrary("nfc_jni");
9913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly    }
10013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pelly
101d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static final String SERVICE_NAME = "nfc";
102fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks
103bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM = android.Manifest.permission.NFC;
104bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String NFC_PERM_ERROR = "NFC permission required";
105bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
106bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly    private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
107a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
10893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
109bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
110225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen    /*package*/ static final String PREF = "NfcServicePrefs";
111f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final String PREF_NFC_ON = "nfc_on";
1130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private static final boolean NFC_ON_DEFAULT = true;
114f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
115a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final String PREF_FIRST_BOOT = "first_boot";
116a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_NDEF_TAG = 0;
118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_CARD_EMULATION = 1;
119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_ACTIVATION = 2;
120b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_LLCP_LINK_DEACTIVATED = 3;
121b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    static final int MSG_TARGET_DESELECTED = 4;
12257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_SHOW_MY_TAG_ICON = 5;
12357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    static final int MSG_HIDE_MY_TAG_ICON = 6;
124b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    static final int MSG_MOCK_NDEF = 7;
125c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_ACTIVATED = 8;
126c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas    static final int MSG_SE_FIELD_DEACTIVATED = 9;
127b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Copied from com.android.nfc_extras to avoid library dependency
12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // Must keep in sync with com.android.nfc_extras
13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_OFF = 1;
13149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
1327efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly
13349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_ON_DETECTED =
13449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
13549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_RF_FIELD_OFF_DETECTED =
13649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
13749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String ACTION_AID_SELECTED =
13849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        "com.android.nfc_extras.action.AID_SELECTED";
13949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
14049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
14174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // TODO: none of these appear to be synchronized but are
14274180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    // read/written from different threads (notably Binder threads)...
143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private int mGeneratedSocketHandle = 0;
14474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick    private volatile boolean mIsNfcEnabled = false;
14549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private boolean mIsDiscoveryOn = false;
14649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
14749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // NFC Execution Environment
14849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    // fields below are protected by this
1490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    private NativeNfcSecureElement mSecureElement;
15049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private OpenSecureElement mOpenEe;  // null when EE closed
15149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private int mEeRoutingState;  // contactless interface routing
1520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1532f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are used in multiple threads and protected by synchronized(this)
1542f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
1552f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
156275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private boolean mScreenUnlocked;
157a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private String mSePackageName;
1582f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
1592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    // fields below are final after onCreate()
16005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton    Context mContext;
1610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private NativeNfcManager mManager;
1620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences mPrefs;
1630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private SharedPreferences.Editor mPrefsEditor;
164533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly    private PowerManager.WakeLock mWakeLock;
165ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushClient mNdefPushClient;
166ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton    NdefPushServer mNdefPushServer;
16776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly    private NfcDispatcher mNfcDispatcher;
168275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks    private KeyguardManager mKeyguard;
169d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
170d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    private static NfcService sService;
171d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
17293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceAdminPerm(Context context) {
17393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
17493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
17593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        if (admin != PackageManager.PERMISSION_GRANTED
17693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton                && nfcee != PackageManager.PERMISSION_GRANTED) {
17793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            throw new SecurityException(ADMIN_PERM_ERROR);
17893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        }
17993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
18093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
18193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    public static void enforceNfceeAdminPerm(Context context) {
18293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton        context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
18393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton    }
18493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton
185d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public static NfcService getInstance() {
186d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        return sService;
187d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
1900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    public void onCreate() {
1912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onCreate();
1922f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
1932f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        Log.i(TAG, "Starting NFC service");
1942f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly
195d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        sService = this;
196d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
1970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext = this;
198275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mManager = new NativeNfcManager(this, this);
1990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mManager.initializeNativeStructure();
20074180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick
201ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushClient = new NdefPushClient(this);
202ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        mNdefPushServer = new NdefPushServer();
20376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly        mNfcDispatcher = new NfcDispatcher(this, mNdefPushClient);
20424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton
2050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        mSecureElement = new NativeNfcSecureElement();
2060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
207275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
2080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor = mPrefs.edit();
209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2107efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly        mIsNfcEnabled = false;  // load from preferences later
211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
212275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
213275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
214533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
215275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
216275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
217533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly
218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
220eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton        IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
22165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_OFF);
22265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        filter.addAction(Intent.ACTION_SCREEN_ON);
223bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
224275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        filter.addAction(Intent.ACTION_USER_PRESENT);
225275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
226bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
227bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter = new IntentFilter();
228bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
229bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        filter.addDataScheme("package");
230bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
231275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        registerReceiver(mReceiver, filter);
2320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Thread t = new Thread() {
2340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            @Override
2350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            public void run() {
2360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
2370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (nfc_on) {
2380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    _enable(false);
239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
240a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                resetSeOnFirstBoot();
241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        };
2430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        t.start();
2440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    @Override
2472f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    public void onTerminate() {
2482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        super.onTerminate();
2492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        // NFC application is persistent, it should not be destroyed by framework
2500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Log.wtf(TAG, "NFC service is under attack!");
2510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
2543ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        /** Protected by "this" */
2553ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton        NdefMessage mLocalMessage = null;
2564acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly
257fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean enable() throws RemoteException {
25993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
2600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
2620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
2630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!previouslyEnabled) {
2640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                reset();
2650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = _enable(previouslyEnabled);
266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
268f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
270fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disable() throws RemoteException {
2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
27393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
2740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean previouslyEnabled = isEnabled();
275ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton            if (DBG) Log.d(TAG, "Disabling NFC.  previous=" + previouslyEnabled);
2760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (previouslyEnabled) {
278aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                isSuccess = _disable(previouslyEnabled);
279f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
281f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
283fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
28405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
28524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                IntentFilter[] filters, TechListParcel techListsParcel) {
286a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Permission check
28705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
288a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
289a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Argument validation
290a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (activity == null || intent == null) {
291ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
292ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
293a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
294a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            // Validate the IntentFilters
295a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            if (filters != null) {
296a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                if (filters.length == 0) {
297a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    filters = null;
298a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                } else {
299a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    for (IntentFilter filter : filters) {
300a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        if (filter == null) {
301a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                            throw new IllegalArgumentException("null IntentFilter");
302a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                        }
303a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                    }
304a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton                }
305a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton            }
306a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton
30724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            // Validate the tech lists
30824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            String[][] techLists = null;
30924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            if (techListsParcel != null) {
31024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton                techLists = techListsParcel.getTechLists();
31124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton            }
31249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
31376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists);
31405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
31505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
31605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
31705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        public void disableForegroundDispatch(ComponentName activity) {
31805973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
31976a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly
32076a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
32105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        }
32205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton
32305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton        @Override
324ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
325ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
326ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (activity == null || msg == null) {
327ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                throw new IllegalArgumentException();
328ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
329ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            if (mNdefPushClient.setForegroundMessage(msg)) {
330ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "Replacing active NDEF push message");
331ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
332ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
333ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
334ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
3352094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        public void enableForegroundNdefPushWithCallback(ComponentName activity,
3362094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                INdefPushCallback callback) {
3372094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
3382094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (activity == null || callback == null) {
3392094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                throw new IllegalArgumentException();
3402094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
3412094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (mNdefPushClient.setForegroundCallback(callback)) {
3422094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks                Log.e(TAG, "Replacing active NDEF push message");
3432094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            }
3442094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        }
3452094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks
3462094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks        @Override
347ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        public void disableForegroundNdefPush(ComponentName activity) {
348ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
3492094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadMsg = mNdefPushClient.setForegroundMessage(null);
3502094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            boolean hadCallback = mNdefPushClient.setForegroundCallback(null);
3512094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks            if (!hadMsg || !hadCallback) {
352ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton                Log.e(TAG, "No active foreground NDEF push message");
353ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            }
354ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        }
355ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton
356ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton        @Override
3570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
358d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
359bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
361f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
362f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Check SAP is not already used */
3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            /* Store the socket handle */
3681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            int sockeHandle = mGeneratedSocketHandle;
3691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpConnectionlessSocket socket;
370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
3711878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpConnectionlessSocket(sap);
3721878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
3731878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
3741878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
3751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
3760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
3771878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
3781878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
3791878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
3821878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
3831878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
3841878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
3851878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
3861878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
3871878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
3881878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
3891878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
3901878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
3911878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
3921878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
395f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
396fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
3970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
3980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
399d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
400bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
405f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4061878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpServiceSocket socket;
4070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
4091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4111878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4121878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4141878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4151878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4161878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
417f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4191878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4201878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4211878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4221878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4231878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4241878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4251878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4261878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4271878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4281878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4291878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
430f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
432f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
433fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
4350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                throws RemoteException {
436d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
437bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
438f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
439f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
440f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
441f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4431878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (DBG) Log.d(TAG, "creating llcp socket");
4441878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            NativeLlcpSocket socket;
445bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
4461878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
447f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
4481878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau            if (socket != null) {
4491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                synchronized(NfcService.this) {
4501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* update socket handle generation */
4511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mGeneratedSocketHandle++;
4520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
4531878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    /* Add the socket into the socket map */
4541878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    mSocketMap.put(mGeneratedSocketHandle, socket);
4551878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                   return mGeneratedSocketHandle;
4560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
457f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
4581878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Get Error Status */
4591878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                int errorStatus = mManager.doGetLastError();
4601878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4611878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
4621878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau
4631878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                switch (errorStatus) {
4641878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_BUFFER_TO_SMALL:
4651878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_BUFFER_TO_SMALL;
4661878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
4671878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
4681878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                    default:
4691878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                        return ErrorCodes.ERROR_SOCKET_CREATION;
4701878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                }
471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
474fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
476d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpConnectionlessSocketService;
4780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
479bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
480fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpSocket getLlcpInterface() throws RemoteException {
482d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpSocket;
4840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
485f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
486fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
488d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mLlcpServerSocketService;
4900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
491f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
492fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public INfcTag getNfcTagInterface() throws RemoteException {
494d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
4950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mNfcTagService;
4960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
4970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
498fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
4990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
500d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pInitiatorService;
5020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
504fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public IP2pTarget getP2pTargetInterface() throws RemoteException {
506d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
5070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mP2pTargetService;
5080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
510bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
51149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public INfcAdapterExtras getNfcAdapterExtrasInterface() {
51293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
51349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mExtrasService;
5140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
5150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
516fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean isEnabled() throws RemoteException {
5180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return mIsNfcEnabled;
5190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
5200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
521fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
522d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public NdefMessage localGet() throws RemoteException {
52357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
52457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
52557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
52657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                return mLocalMessage;
52757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
528d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
529d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton
530d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        @Override
531d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        public void localSet(NdefMessage message) throws RemoteException {
53293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceAdminPerm(mContext);
53357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
53457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            synchronized (this) {
53557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                mLocalMessage = message;
53657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = NfcService.this.getApplicationContext();
53757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
53857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Send a message to the UI thread to show or hide the icon so the requests are
53957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // serialized and the icon can't get out of sync with reality.
54057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                if (message != null) {
54157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    FileOutputStream out = null;
54257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
54357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
54457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
54557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        byte[] bytes = message.toByteArray();
54657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (bytes.length == 0) {
54757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            Log.w(TAG, "Setting a empty mytag");
54857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
54957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
55057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        out.write(bytes);
55157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
55257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        Log.e(TAG, "Could not write mytag file", e);
55357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } finally {
55457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        try {
55557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            if (out != null) {
55657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.flush();
55757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                                out.close();
55857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            }
55957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        } catch (IOException e) {
56057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            // Ignore
56157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
56257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
56357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
56457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Only show the icon if NFC is enabled.
56557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    if (mIsNfcEnabled) {
56657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        sendMessage(MSG_SHOW_MY_TAG_ICON, null);
56757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
56857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } else {
56957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
57057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    sendMessage(MSG_HIDE_MY_TAG_ICON, null);
57157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
57257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
573d65348455ae09a467f288d65dbf924fc60c8d290Jeff Hamilton        }
5743fb14d0868594c78a777e805545209636814e223Martijn Coenen
5750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
5760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
5770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
578f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
579f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpSocket findSocket(int nativeHandle) {
580bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
581bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpSocket)) {
582f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
583f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
584bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpSocket) socket;
585f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
586f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
587fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
5880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int close(int nativeHandle) throws RemoteException {
589d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
590bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
591f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
592f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
593f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
596f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
597f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
598f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
599f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
600f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
6011878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
6021878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
6031878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
6041878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                return ErrorCodes.SUCCESS;
605f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
607f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
608f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
609f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
610fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle, int sap) throws RemoteException {
612d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
613bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
614f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
6150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
616f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
617f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
618f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
619f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
620f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
621f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
622f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
623f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
624f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
62593915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnect(sap);
6260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
6270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
628f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
629f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
630f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
631f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
632f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
633f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
635f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
636f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
637fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connectByName(int nativeHandle, String sn) throws RemoteException {
639d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
640bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
641f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpSocket socket = null;
642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
643f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
644f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
645f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
648f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
649f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
650f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
651f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
65293915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                isSuccess = socket.doConnectBy(sn);
653f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
654f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
655f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
656f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
657f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
658f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
660f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
662f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
663f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
664fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSap(int nativeHandle) throws RemoteException {
666d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
667bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
670f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
671f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
672f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
673f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
674f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
6750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
676f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
6770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
6780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getSap();
679f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
6800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
681f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
682f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
683f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
684fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
6850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
686d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
687bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
6880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
689f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
690f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
691f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
693f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
694f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
695f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
696f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
6980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getMiu();
6990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
701f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
703f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
704fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
706d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
707bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
7080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
709f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
710f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
711f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
712f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
715f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
716f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return socket.getRw();
7190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return 0;
7210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
724fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
726d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
7310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
7320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
7330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
736f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketMiu() != 0) {
7390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketMiu();
7400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
7410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
748fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
750d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
760f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
7620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket.doGetRemoteSocketRw() != 0) {
7630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return socket.doGetRemoteSocketRw();
7640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
7650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
7670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
7680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
7690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
772fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
774d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
7800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
7810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
784f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
78628f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return socket.doReceive(receiveBuffer);
7870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
78828f72bd9880d0b00c486603489d3862733eb638fSylvain Fonteneau                return 0;
7890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
7900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
7910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
792fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
7930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int send(int nativeHandle, byte[] data) throws RemoteException {
794d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
7950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket socket = null;
7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
805f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = socket.doSend(data);
8080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess) {
8090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
8100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
8120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            } else {
8140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_IO;
8150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
8180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
821f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpServiceSocket findSocket(int nativeHandle) {
822bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
823bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpServiceSocket)) {
824f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
825f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
826bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpServiceSocket) socket;
827f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
828f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
829fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int accept(int nativeHandle) throws RemoteException {
831d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
8340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpSocket clientSocket = null;
8350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
8390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                /* find the socket in the hmap */
842f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                socket = findSocket(nativeHandle);
8430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (socket != null) {
84493915e1c6fe6d5d16fcebeda610782bf5812c9b4Nick Pelly                    clientSocket = socket.doAccept(socket.getMiu(),
8450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                            socket.getRw(), socket.getLinearBufferLength());
8460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    if (clientSocket != null) {
8470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        /* Add the socket into the socket map */
8482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        synchronized(this) {
8491878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mGeneratedSocketHandle++;
8501878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            mSocketMap.put(mGeneratedSocketHandle, clientSocket);
8511878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                            return mGeneratedSocketHandle;
8522f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                        }
8530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    } else {
8540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                        return ErrorCodes.ERROR_IO;
8550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    }
8560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                } else {
8570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.ERROR_IO;
8580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
8600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
861fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
8620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void close(int nativeHandle) throws RemoteException {
863d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
8640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeLlcpServiceSocket socket = null;
8660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
8680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
8690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return;
8700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
8720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the socket in the hmap */
873f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
8740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (socket != null) {
8751878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
876f63da5f0887eba86d877faaee41dc5dfb8fccd50Jeff Hamilton                synchronized (this) {
8770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Remove the socket closed from the hmap */
8780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    RemoveSocket(nativeHandle);
8790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
8800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
8810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
882f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
884f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
885f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
886f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
887bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            Object socket = NfcService.this.findSocket(nativeHandle);
888bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
889f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau                return null;
890f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            }
891bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return (NativeLlcpConnectionlessSocket) socket;
892f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau        }
893f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau
894fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
895f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public void close(int nativeHandle) throws RemoteException {
896d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
897bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
898f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
899f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
901f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
902f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return;
903f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
904f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
906f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
9081878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                socket.doClose();
9091878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                /* Remove the socket closed from the hmap */
9101878c7b6e2cef1e52138ee3a5588913cc165faa5Sylvain Fonteneau                RemoveSocket(nativeHandle);
911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
914fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getSap(int nativeHandle) throws RemoteException {
916d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
917bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
919f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
920f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
921f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
923f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
924f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
926f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
928f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return socket.getSap();
929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
930f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return 0;
931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
934fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
936d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
937bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            LlcpPacket packet;
940f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
945f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
947f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                packet = socket.doReceiveFrom(socket.getLinkMiu());
950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (packet != null) {
951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return packet;
952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
959fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
961d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
962bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeLlcpConnectionlessSocket socket = null;
964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the socket in the hmap */
972f5d6f3253dca74631ba78c715f224cfa80e61d29Sylvain Fonteneau            socket = findSocket(nativeHandle);
973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (socket != null) {
974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (isSuccess) {
976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.SUCCESS;
977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } else {
978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return ErrorCodes.ERROR_IO;
979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            } else {
981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private final INfcTag mNfcTagService = new INfcTag.Stub() {
987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
988fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int close(int nativeHandle) throws RemoteException {
990d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
991bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1002b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                /* Remove the device from the hmap */
1003b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                unregisterObject(nativeHandle);
100421545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly                tag.disconnect();
1005b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.SUCCESS;
1006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1007f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* Restart polling loop for notification */
100849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_DISCONNECT;
1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1012fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1013ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen        public int connect(int nativeHandle, int technology) throws RemoteException {
1014d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1015bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = 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 tag in the hmap */
1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1025b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1026b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return ErrorCodes.ERROR_DISCONNECT;
1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1028ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen
10291b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            if (technology == TagTechnology.NFC_B) {
10301b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen                return ErrorCodes.ERROR_NOT_SUPPORTED;
10311b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen            }
10321b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen
1033ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // Note that on most tags, all technologies are behind a single
1034ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // handle. This means that the connect at the lower levels
1035ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            // will do nothing, as the tag is already connected to that handle.
1036ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            if (tag.connect(technology)) {
1037ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.SUCCESS;
1038ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            } else {
1039ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen                return ErrorCodes.ERROR_DISCONNECT;
1040ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen            }
1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1042f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1043fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1044aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        public int reconnect(int nativeHandle) throws RemoteException {
1045aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1046aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1047aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            NativeNfcTag tag = null;
1048aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1049aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            // Check if NFC is enabled
1050aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (!mIsNfcEnabled) {
1051aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
1052aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1053aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1054aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            /* find the tag in the hmap */
1055aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
1056aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            if (tag != null) {
1057aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                if (tag.reconnect()) {
1058aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.SUCCESS;
1059aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                } else {
1060aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                    return ErrorCodes.ERROR_DISCONNECT;
1061aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen                }
1062aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            }
1063aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen            return ErrorCodes.ERROR_DISCONNECT;
1064aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        }
1065aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen
1066aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen        @Override
1067b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        public int[] getTechList(int nativeHandle) throws RemoteException {
1068d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1069bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1070f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1071f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1073f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1074f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1076b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton            NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
1077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1078b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                return tag.getTechList();
1079f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1080f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1081f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1082f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1083fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1084f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public byte[] getUid(int nativeHandle) throws RemoteException {
1085f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1086f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] uid;
1087f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1088f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1089f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1090f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1091f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1092f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1093f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1094f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1096f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                uid = tag.getUid();
1097f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return uid;
1098f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1101f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1102fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1103b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public boolean isPresent(int nativeHandle) throws RemoteException {
1104b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            NativeNfcTag tag = null;
1105b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1106b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            // Check if NFC is enabled
1107b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (!mIsNfcEnabled) {
1108b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1109b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1110b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1111b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            /* find the tag in the hmap */
1112b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            tag = (NativeNfcTag) findObject(nativeHandle);
1113b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag == null) {
1114b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                return false;
1115b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            }
1116b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1117ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen            return tag.isPresent();
1118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
1119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
1120fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public boolean isNdef(int nativeHandle) throws RemoteException {
1122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1123f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            boolean isSuccess = false;
1124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1126f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1127f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return isSuccess;
1128f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1129f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1131f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
11323ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen            int[] ndefInfo = new int[2];
1133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
11343ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen                isSuccess = tag.checkNdef(ndefInfo);
1135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return isSuccess;
1137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1138f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1139fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11409d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen        public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
114197c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1142d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1143bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag = null;
1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            byte[] response;
1146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1152f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
11559d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                int[] targetLost = new int[1];
11569d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                response = tag.transceive(data, raw, targetLost);
11579d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                TransceiveResult transResult = new TransceiveResult(
11589d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (response != null) ? true : false,
11599d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        (targetLost[0] == 1) ? true : false,
11609d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                        response);
11619d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen                return transResult;
1162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1165f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1166fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11673fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1168d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1169bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return null;
1175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1176f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1177f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1178f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag != null) {
1180b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                byte[] buf = tag.read();
1181f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                if (buf == null)
1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Create an NdefMessage */
1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                try {
1186f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return new NdefMessage(buf);
1187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                } catch (FormatException e) {
1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    return null;
1189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                }
1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return null;
1192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1193f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1194fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
11953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1196d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1197bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly
1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            NativeNfcTag tag;
1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            // Check if NFC is enabled
1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (!mIsNfcEnabled) {
1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            /* find the tag in the hmap */
1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            tag = (NativeNfcTag) findObject(nativeHandle);
1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            if (tag == null) {
1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1211b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau            if (tag.write(msg.toByteArray())) {
1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.SUCCESS;
1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            else {
1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                return ErrorCodes.ERROR_IO;
1216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1220fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        public int getLastError(int nativeHandle) throws RemoteException {
1222bb78d3749bd0cc3801fdd9d5df06b0f6ee7a400fMartijn Coenen            return(mManager.doGetLastError());
1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1225fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
12273fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            throw new UnsupportedOperationException();
1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1230fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
12313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
123203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
123303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
123403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            NativeNfcTag tag;
123503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
123603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            // Check if NFC is enabled
123703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (!mIsNfcEnabled) {
123803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
123903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
124003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
124103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            /* find the tag in the hmap */
124203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
124303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag == null) {
124403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
124503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
124603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen
124703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            if (tag.makeReadonly()) {
124803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.SUCCESS;
124903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
125003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            else {
125103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen                return ErrorCodes.ERROR_IO;
125203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen            }
1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1254f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
12550aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        @Override
12560aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
12570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            NativeNfcTag tag;
12600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12610aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            // Check if NFC is enabled
12620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (!mIsNfcEnabled) {
12630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_NOT_INITIALIZED;
12640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
12650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            /* find the tag in the hmap */
12670aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
12680aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag == null) {
12690aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
12700aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
12710aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            if (tag.formatNdef(key)) {
12730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.SUCCESS;
12740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
12750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            else {
12760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen                return ErrorCodes.ERROR_IO;
12770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen            }
12780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen        }
12790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen
12801b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
12813fb14d0868594c78a777e805545209636814e223Martijn Coenen        public Tag rediscover(int nativeHandle) throws RemoteException {
12823fb14d0868594c78a777e805545209636814e223Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
12833fb14d0868594c78a777e805545209636814e223Martijn Coenen
12843fb14d0868594c78a777e805545209636814e223Martijn Coenen            NativeNfcTag tag = null;
12853fb14d0868594c78a777e805545209636814e223Martijn Coenen
12863fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Check if NFC is enabled
12873fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (!mIsNfcEnabled) {
12883fb14d0868594c78a777e805545209636814e223Martijn Coenen                return null;
12893fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
12903fb14d0868594c78a777e805545209636814e223Martijn Coenen
12913fb14d0868594c78a777e805545209636814e223Martijn Coenen            /* find the tag in the hmap */
12923fb14d0868594c78a777e805545209636814e223Martijn Coenen            tag = (NativeNfcTag) findObject(nativeHandle);
12933fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (tag != null) {
12943fb14d0868594c78a777e805545209636814e223Martijn Coenen                // For now the prime usecase for rediscover() is to be able
12953fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to access the NDEF technology after formatting without
12963fb14d0868594c78a777e805545209636814e223Martijn Coenen                // having to remove the tag from the field, or similar
12973fb14d0868594c78a777e805545209636814e223Martijn Coenen                // to have access to NdefFormatable in case low-level commands
12983fb14d0868594c78a777e805545209636814e223Martijn Coenen                // were used to remove NDEF. So instead of doing a full stack
12993fb14d0868594c78a777e805545209636814e223Martijn Coenen                // rediscover (which is poorly supported at the moment anyway),
13003fb14d0868594c78a777e805545209636814e223Martijn Coenen                // we simply remove these two technologies and detect them
13013fb14d0868594c78a777e805545209636814e223Martijn Coenen                // again.
13023fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF);
13033fb14d0868594c78a777e805545209636814e223Martijn Coenen                tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
13043fb14d0868594c78a777e805545209636814e223Martijn Coenen                NdefMessage[] msgs = findAndReadNdef(tag);
13053fb14d0868594c78a777e805545209636814e223Martijn Coenen                // Build a new Tag object to return
13063fb14d0868594c78a777e805545209636814e223Martijn Coenen                Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
13073fb14d0868594c78a777e805545209636814e223Martijn Coenen                        tag.getTechExtras(), tag.getHandle(), mNfcTagService);
13083fb14d0868594c78a777e805545209636814e223Martijn Coenen                return newTag;
13093fb14d0868594c78a777e805545209636814e223Martijn Coenen            }
13103fb14d0868594c78a777e805545209636814e223Martijn Coenen            return null;
13113fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
13123fb14d0868594c78a777e805545209636814e223Martijn Coenen
13133fb14d0868594c78a777e805545209636814e223Martijn Coenen
13143fb14d0868594c78a777e805545209636814e223Martijn Coenen        @Override
13151b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        public void setIsoDepTimeout(int timeout) throws RemoteException {
13161b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13171b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
13181b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mManager.setIsoDepTimeout(timeout);
13191b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13211b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        @Override
1322dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void setFelicaTimeout(int timeout) throws RemoteException {
13231b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
13241b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen
1325dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mManager.setFelicaTimeout(timeout);
1326dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        }
1327dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1328dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        @Override
1329dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen        public void resetTimeouts() throws RemoteException {
1330dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1331dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen
1332dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen            mManager.resetTimeouts();
13331b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen        }
13340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1338fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1340d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
13470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
13500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
13510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
13520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
13530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
13540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
13550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
13560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
13580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1360fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1362d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1363f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
13690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
13720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
13730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
13740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
13750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1376f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1379fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
13800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] receive(int nativeHandle) throws RemoteException {
1381d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
13860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
13870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
13880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
13900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
13910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
13920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
13930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doReceive();
13940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
13950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
13960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
13970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
13980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Restart polling loop for notification */
139949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
14000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
14010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1403fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
1405d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
14080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1409f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
14130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
14160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
14170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                isSuccess = device.doSend(data);
14190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
14210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
14220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1423f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
1425f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1426fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int connect(int nativeHandle) throws RemoteException {
1428d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1429f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1431f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
14350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1436f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
14380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
14390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (device.doConnect()) {
14410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return ErrorCodes.SUCCESS;
14420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
14430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_CONNECT;
14450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1446f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1447fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public boolean disconnect(int nativeHandle) throws RemoteException {
1449d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1450f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
14520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            boolean isSuccess = false;
1453f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14540e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return isSuccess;
14570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
1458f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
14600e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
14610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (isSuccess = device.doDisconnect()) {
14630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* remove the device from the hmap */
1464b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                    unregisterObject(nativeHandle);
14650e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    /* Restart polling loop for notification */
146649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    applyRouting();
14670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                }
1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
14690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return isSuccess;
1470f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14710e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1472f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1473fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
1475d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
14780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
14790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
14800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
14810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1482f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1483f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
14850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
14860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
14870e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.getGeneralBytes();
14880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
14890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
14900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
14910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
14920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
14930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1494f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1495fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
14960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public int getMode(int nativeHandle) throws RemoteException {
1497d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
14990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return ErrorCodes.ERROR_NOT_INITIALIZED;
1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1505f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15060e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return device.getMode();
15100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return ErrorCodes.ERROR_INVALID_PARAM;
15120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1513f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1514fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
151597c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen        public byte[] transceive(int nativeHandle, byte[] data)
151697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen                throws RemoteException {
1517d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1518f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15190e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            NativeP2pDevice device;
1520f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            // Check if NFC is enabled
15220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (!mIsNfcEnabled) {
15230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return null;
1524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
1525f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
15260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* find the device in the hmap */
15270e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            device = (NativeP2pDevice) findObject(nativeHandle);
15280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            if (device != null) {
15290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                byte[] buff = device.doTransceive(data);
15300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                if (buff == null)
15310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                    return null;
15320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                return buff;
15330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            }
15340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            return null;
15350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
15360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    };
1537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1538dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
1539dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // Blocks until a pending open() or transceive() times out.
1540dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        //TODO: This is incorrect behavior - the close should interrupt pending
1541dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        // operations. However this is not supported by current hardware.
1542dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1543dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        synchronized(NfcService.this) {
1544dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (!mIsNfcEnabled) {
1545dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC adapter is disabled");
1546dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1547dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (mOpenEe == null) {
1548dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new IOException("NFC EE closed");
1549dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1550dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
1551dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                throw new SecurityException("Wrong PID");
1552dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            }
1553dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1554c8288824e2f5513dfe59b78d5f3af7757a1945b4Nick Pelly            mManager.resetTimeouts();
1555dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mSecureElement.doDisconnect(mOpenEe.handle);
1556dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            mOpenEe = null;
1557dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
1558dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly            applyRouting();
1559dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly        }
1560dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly    }
1561dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly
156249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
156349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeNoException() {
156449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
156549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", 0);
156649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
156749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
156849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private Bundle writeIoException(IOException e) {
156949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle p = new Bundle();
157049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putInt("e", -1);
157149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            p.putString("m", e.getMessage());
157249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return p;
157349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
15740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1575bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
157649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle open(IBinder b) throws RemoteException {
157793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1578bd555ee64250126b60b24814120a2049943920caNick Pelly
157949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
158049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
158149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                _open(b);
158249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
158349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
158449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
15850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
158649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
158749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
15880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
158949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private void _open(IBinder b) throws IOException, RemoteException {
159049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
159149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
159249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC adapter is disabled");
159349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
159449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe != null) {
159549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE already open");
159649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
15970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
159849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                int handle = mSecureElement.doOpenSecureElementConnection();
159949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (handle == 0) {
160049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE failed to open");
160149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
1602ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly                mManager.doSetIsoDepTimeout(10000);
1603ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly
160449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mOpenEe = new OpenSecureElement(getCallingPid(), handle);
160549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                try {
160649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    b.linkToDeath(mOpenEe, 0);
160749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } catch (RemoteException e) {
160849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mOpenEe.binderDied();
160949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
161049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly           }
16110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1613bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
161449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle close() throws RemoteException {
161593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
16160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
161749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
161849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
1619dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                _nfcEeClose(true, getCallingPid());
162049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
162149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
162249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16230bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
162449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
162549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1627bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
162849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public Bundle transceive(byte[] in) throws RemoteException {
162993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
1630bd555ee64250126b60b24814120a2049943920caNick Pelly
163149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            Bundle result;
163249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            byte[] out;
163349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            try {
163449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                out = _transceive(in);
163549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeNoException();
163649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result.putByteArray("out", out);
163749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            } catch (IOException e) {
163849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                result = writeIoException(e);
16390bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
164049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return result;
164149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
16420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
164349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        private byte[] _transceive(byte[] data) throws IOException, RemoteException {
164449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized(NfcService.this) {
164549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (!mIsNfcEnabled) {
164649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC is not enabled");
164749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
164849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mOpenEe == null){
164949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new IOException("NFC EE is not open");
165049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
165149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (getCallingPid() != mOpenEe.pid) {
165249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    throw new SecurityException("Wrong PID");
165349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                }
16540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
16550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
165649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mSecureElement.doTransceive(mOpenEe.handle, data);
16570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1659bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
166049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int getCardEmulationRoute() throws RemoteException {
166193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
166249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            return mEeRoutingState;
16630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
1665bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
166649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void setCardEmulationRoute(int route) throws RemoteException {
166793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton            NfcService.enforceNfceeAdminPerm(mContext);
166849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mEeRoutingState = route;
166949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
16700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    };
16720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
167349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** resources kept while secure element is open */
167449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private class OpenSecureElement implements IBinder.DeathRecipient {
167549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int pid;  // pid that opened SE
167649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public int handle; // low-level handle
167749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public OpenSecureElement(int pid, int handle) {
167849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.pid = pid;
167949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            this.handle = handle;
168049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        }
1681bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        @Override
168249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        public void binderDied() {
168349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            synchronized (NfcService.this) {
168449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
168549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                pid = -1;
16860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas                try {
1687dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                    _nfcEeClose(false, -1);
1688dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly                } catch (IOException e) { /* already closed */ }
16890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas            }
16900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas        }
16910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas    }
16920bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas
16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private boolean _enable(boolean oldEnabledState) {
16940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        boolean isSuccess = mManager.initialize();
16950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        if (isSuccess) {
169665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            mIsNfcEnabled = true;
169749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            mIsDiscoveryOn = true;
169865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
16990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            /* Start polling loop */
170049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly            applyRouting();
170157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
170257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            /* bring up the my tag server */
1703ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton            mNdefPushServer.start();
170457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
1705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        } else {
1706aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            Log.w(TAG, "Error enabling NFC");
17070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly            mIsNfcEnabled = false;
1708f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1709f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        updateNfcOnSetting(oldEnabledState);
1711f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
17120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        return isSuccess;
1713f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1714f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1715aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    private boolean _disable(boolean oldEnabledState) {
1716aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean isSuccess;
1717aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1718aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        /* tear down the my tag server */
1719aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mNdefPushServer.stop();
1720aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1721aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // Stop watchdog if tag present
1722aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // A convenient way to stop the watchdog properly consists of
1723aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // disconnecting the tag. The polling loop shall be stopped before
1724aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        // to avoid the tag being discovered again.
1725aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        mIsDiscoveryOn = false;
1726aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        applyRouting();
1727aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        maybeDisconnectTarget();
1728aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1729aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        isSuccess = mManager.deinitialize();
1730aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
1731aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (isSuccess) {
1732aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mIsNfcEnabled = false;
17338586b104c1cf07c52c739c0afab0ded1bf151859Nick Pelly            mNfcDispatcher.disableForegroundDispatch();
1734aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            mNdefPushClient.setForegroundMessage(null);
1735aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1736aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1737aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        updateNfcOnSetting(oldEnabledState);
1738aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1739aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        return isSuccess;
1740aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly    }
1741aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
174249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    /** apply NFC discovery and EE routing */
174349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly    private synchronized void applyRouting() {
174449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly        if (mIsNfcEnabled && mOpenEe == null) {
1745275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (mScreenUnlocked) {
174649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
174749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing ON");
17487efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly                    mManager.doSelectSecureElement();
174949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
175049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-EE routing OFF");
17517efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly                    mManager.doDeselectSecureElement();
1752221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
175349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                if (mIsDiscoveryOn) {
175449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery ON");
17557efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly                    mManager.enableDiscovery();
175649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                } else {
175749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    Log.d(TAG, "NFC-C discovery OFF");
175849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                    mManager.disableDiscovery();
1759221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas                }
1760221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            } else {
176149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-EE routing OFF");
17627efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly                mManager.doDeselectSecureElement();
176349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                Log.d(TAG, "NFC-C discovery OFF");
176449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                mManager.disableDiscovery();
1765221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas            }
176665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly        }
176765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly    }
176865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly
17692436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    /** Disconnect any target if present */
17702436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    private synchronized void maybeDisconnectTarget() {
17712436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        if (mIsNfcEnabled) {
17722436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            Iterator<?> iterator = mObjectMap.values().iterator();
17732436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            while(iterator.hasNext()) {
17742436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                Object object = iterator.next();
1775663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                if(object instanceof NativeNfcTag) {
1776663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from tags
17772436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    NativeNfcTag tag = (NativeNfcTag) object;
17782436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                    tag.disconnect();
17792436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir                }
1780663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                else if(object instanceof NativeP2pDevice) {
1781663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    // Disconnect from P2P devices
1782663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    NativeP2pDevice device = (NativeP2pDevice) object;
1783663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
1784663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is target, request disconnection
1785663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        device.doDisconnect();
1786663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
1787663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    else {
1788663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Remote peer is initiator, we cannot disconnect
1789663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                        // Just wait for field removal
1790663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                    }
1791663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                }
1792663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                iterator.remove();
17932436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir            }
17942436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir        }
17952436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir    }
17962436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir
1797a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    //TODO: dont hardcode this
1798a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private static final byte[][] SE_RESET_APDUS = {
1799a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1800a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1801a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
1802a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1803a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick 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},
1804a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
1805a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
1806a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    };
1807bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1808a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private void resetSeOnFirstBoot() {
1809a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
1810a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.i(TAG, "First Boot");
1811a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            executeSeReset();
1812a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
1813a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mPrefsEditor.apply();
1814a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1815a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    }
1816bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1817a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private synchronized void executeSeReset() {
1818a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        // TODO: read SE reset list from /system/etc
1819a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        //List<byte[]> apdus = readSeResetApdus();
1820a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        byte[][]apdus = SE_RESET_APDUS;
1821a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (apdus == null) {
1822a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1823a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1824aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1825aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        boolean tempEnable = !mIsNfcEnabled;
1826aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
1827aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (!_enable(false)) {
1828aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                Log.w(TAG, "Could not enable NFC to reset EE!");
1829aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                return;
1830aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1831aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1832aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1833a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        Log.i(TAG, "Executing SE Reset Script");
1834a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        int handle = mSecureElement.doOpenSecureElementConnection();
1835a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        if (handle == 0) {
1836a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "Could not open the secure element!");
1837aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            if (tempEnable) {
1838aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly                _disable(true);
1839aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            }
1840a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return;
1841a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        }
1842bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1843a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        for (byte[] cmd : apdus) {
1844a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            mSecureElement.doTransceive(handle, cmd);
1845bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1846a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly
1847a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        mSecureElement.doDisconnect(handle);
1848aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly
1849aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        if (tempEnable) {
1850aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly            _disable(true);
1851aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly        }
1852bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
1853bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1854a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly    private List<byte[]> readSeResetApdus() {
1855a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        FileInputStream input = null;
1856a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        List<byte[]> apdus = null;
1857bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1858bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        try {
1859a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
1860a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            DataInputStream stream = new DataInputStream(input);
1861bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1862a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            int commandsSize = stream.readInt();
1863a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = new ArrayList<byte[]>(commandsSize);
1864bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1865a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            for (int i = 0 ; i < commandsSize ; i++) {
1866a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                int length = stream.readInt();
1867bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1868a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                byte[] cmd = new byte[length];
1869bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1870a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                stream.read(cmd);
1871a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                apdus.add(cmd);
1872bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1873bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
1874a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            return apdus;
1875a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        } catch (FileNotFoundException e) {
1876a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
1877bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } catch (IOException e) {
1878a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            Log.e(TAG, "SE Reset Script corrupt: ", e);
1879a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly            apdus = null;
1880bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        } finally {
1881bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            try {
1882a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                if (input != null) {
1883a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                    input.close();
1884bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
1885bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } catch (IOException e) {
1886bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                // Ignore
1887bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            }
1888bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks        }
1889a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly        return apdus;
1890bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks    }
1891bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks
18920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void updateNfcOnSetting(boolean oldEnabledState) {
18930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
18942f386c612159a48933c12dbcaf6735bd9ad1c660Brad Fitzpatrick        mPrefsEditor.apply();
18950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
18962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly        synchronized(this) {
18974acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly            if (oldEnabledState != mIsNfcEnabled) {
18982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
18994acf84356e35861f7df6d07a2b9ff84842a9f221Nick Pelly                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
19002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
19012f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly                mContext.sendBroadcast(intent);
19022f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly            }
190357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
190457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            if (mIsNfcEnabled) {
190557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
190657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                Context context = getApplicationContext();
190757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
190857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // Set this to null by default. If there isn't a tag on disk
190957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // or if there was an error reading the tag then this will cause
191057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                // the status bar icon to be removed.
191157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                NdefMessage myTag = null;
191257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
191357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                FileInputStream input = null;
191457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
191557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
191657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    input = context.openFileInput(MY_TAG_FILE_NAME);
191757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
191857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
191957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    byte[] buffer = new byte[4096];
192057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    int read = 0;
192157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    while ((read = input.read(buffer)) > 0) {
192257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        bytes.write(buffer, 0, read);
192357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
192457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
192557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    myTag = new NdefMessage(bytes.toByteArray());
192657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FileNotFoundException e) {
192757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore.
192857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (IOException e) {
192957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Could not read mytag file: ", e);
193057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
193157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (FormatException e) {
193257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    Log.e(TAG, "Invalid NdefMessage for mytag", e);
193357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    context.deleteFile(MY_TAG_FILE_NAME);
193457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } finally {
193557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    try {
193657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        if (input != null) {
193757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                            input.close();
193857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        }
193957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    } catch (IOException e) {
194057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                        // Ignore
194157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    }
194257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
194357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
194457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                try {
194557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    mNfcAdapter.localSet(myTag);
194657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                } catch (RemoteException e) {
194757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                    // Ignore
194857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                }
194957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            } else {
195057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                sendMessage(MSG_HIDE_MY_TAG_ICON, null);
195157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton            }
19520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        }
1953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    // Reset all internals
19562f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized void reset() {
195774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // TODO: none of these appear to be synchronized but are
195874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick        // read/written from different threads (notably Binder threads)...
1959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Clear tables
1961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mObjectMap.clear();
1962f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.clear();
1963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        // Reset variables
1965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mIsNfcEnabled = false;
1966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findObject(int key) {
1969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        Object device = null;
1970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        device = mObjectMap.get(key);
1972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        if (device == null) {
1973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            Log.w(TAG, "Handle not found !");
1974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
1975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1976f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        return device;
1977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1978f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void registerTagObject(NativeNfcTag nativeTag) {
1980b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.put(nativeTag.getHandle(), nativeTag);
1981b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
1982b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
19832f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    synchronized void unregisterObject(int handle) {
1984b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mObjectMap.remove(handle);
1985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
19872f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly    private synchronized Object findSocket(int key) {
1988bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        if (mSocketMap == null) {
1989bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly            return null;
1990bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        }
1991bfb74ec41fe9d2d1ce72467888432f0b3296425fNick Pelly        return mSocketMap.get(key);
1992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    private void RemoveSocket(int key) {
1995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        mSocketMap.remove(key);
1996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    }
1997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
1998d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
1999d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
2000d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2001d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
20021be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
20031be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
20041be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
20051be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2006d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpSocket(mLlcpSocket, handle);
2007d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2008d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2009d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2010d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2011d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2012d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
2013d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    /** For use by code in this process */
2014d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
2015d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int linearBufferLength) {
2016d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        try {
2017d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
20181be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            if (ErrorCodes.isError(handle)) {
20191be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
20201be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton                return null;
20211be4eb6d61c4b6e02c5a5cb7ac3b3a68cae7d7a2Jeff Hamilton            }
2022d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
2023d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        } catch (RemoteException e) {
2024d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            // This will never happen since the code is calling into it's own process
2025d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton            throw new IllegalStateException("unable to talk to myself", e);
2026d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton        }
2027d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton    }
2028d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
20290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private void activateLlcpLink() {
20300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        /* Broadcast Intent Link LLCP activated */
20310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        Intent LlcpLinkIntent = new Intent();
20320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
20340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
20350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly                NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
2036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
2037ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton        if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
20380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
20390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    }
2040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
204157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    public void sendMockNdefTag(NdefMessage msg) {
2042b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton        sendMessage(MSG_MOCK_NDEF, msg);
204357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton    }
204457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2045b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    void sendMessage(int what, Object obj) {
2046b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        Message msg = mHandler.obtainMessage();
2047b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.what = what;
2048b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        msg.obj = obj;
2049b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        mHandler.sendMessage(msg);
2050b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau    }
2051b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
20523fb14d0868594c78a777e805545209636814e223Martijn Coenen    static public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
20533fb14d0868594c78a777e805545209636814e223Martijn Coenen        // Try to find NDEF on any of the technologies.
20543fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] technologies = nativeTag.getTechList();
20553fb14d0868594c78a777e805545209636814e223Martijn Coenen        int[] handles = nativeTag.getHandleList();
20563fb14d0868594c78a777e805545209636814e223Martijn Coenen        int techIndex = 0;
20573fb14d0868594c78a777e805545209636814e223Martijn Coenen        int lastHandleScanned = 0;
20583fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean ndefFoundAndConnected = false;
20593fb14d0868594c78a777e805545209636814e223Martijn Coenen        NdefMessage[] ndefMsgs = null;
20603fb14d0868594c78a777e805545209636814e223Martijn Coenen        boolean foundFormattable = false;
20613fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableHandle = 0;
20623fb14d0868594c78a777e805545209636814e223Martijn Coenen        int formattableLibNfcType = 0;
20633fb14d0868594c78a777e805545209636814e223Martijn Coenen
20643fb14d0868594c78a777e805545209636814e223Martijn Coenen        while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) {
20653fb14d0868594c78a777e805545209636814e223Martijn Coenen            if (handles[techIndex] != lastHandleScanned) {
20663fb14d0868594c78a777e805545209636814e223Martijn Coenen                // We haven't seen this handle yet, connect and checkndef
20673fb14d0868594c78a777e805545209636814e223Martijn Coenen                if (nativeTag.connect(technologies[techIndex])) {
20683fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Check if this type is NDEF formatable
20693fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (!foundFormattable) {
20703fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (nativeTag.isNdefFormatable()) {
20713fb14d0868594c78a777e805545209636814e223Martijn Coenen                            foundFormattable = true;
20723fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableHandle = nativeTag.getConnectedHandle();
20733fb14d0868594c78a777e805545209636814e223Martijn Coenen                            formattableLibNfcType = nativeTag.getConnectedLibNfcType();
20743fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // We'll only add formattable tech if no ndef is
20753fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // found - this is because libNFC refuses to format
20763fb14d0868594c78a777e805545209636814e223Martijn Coenen                            // an already NDEF formatted tag.
20773fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
20783fb14d0868594c78a777e805545209636814e223Martijn Coenen                        nativeTag.reconnect();
20793fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, already found formattable technology
20803fb14d0868594c78a777e805545209636814e223Martijn Coenen
20813fb14d0868594c78a777e805545209636814e223Martijn Coenen                    int[] ndefinfo = new int[2];
20823fb14d0868594c78a777e805545209636814e223Martijn Coenen                    if (nativeTag.checkNdef(ndefinfo)) {
20833fb14d0868594c78a777e805545209636814e223Martijn Coenen                        ndefFoundAndConnected = true;
20843fb14d0868594c78a777e805545209636814e223Martijn Coenen                        boolean generateEmptyNdef = false;
20853fb14d0868594c78a777e805545209636814e223Martijn Coenen
20863fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int supportedNdefLength = ndefinfo[0];
20873fb14d0868594c78a777e805545209636814e223Martijn Coenen                        int cardState = ndefinfo[1];
20883fb14d0868594c78a777e805545209636814e223Martijn Coenen                        byte[] buff = nativeTag.read();
20893fb14d0868594c78a777e805545209636814e223Martijn Coenen                        if (buff != null) {
20903fb14d0868594c78a777e805545209636814e223Martijn Coenen                            ndefMsgs = new NdefMessage[1];
20913fb14d0868594c78a777e805545209636814e223Martijn Coenen                            try {
20923fb14d0868594c78a777e805545209636814e223Martijn Coenen                                ndefMsgs[0] = new NdefMessage(buff);
20933fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.addNdefTechnology(ndefMsgs[0],
20943fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedHandle(),
20953fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedLibNfcType(),
20963fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        nativeTag.getConnectedTechnology(),
20973fb14d0868594c78a777e805545209636814e223Martijn Coenen                                        supportedNdefLength, cardState);
20983fb14d0868594c78a777e805545209636814e223Martijn Coenen                                nativeTag.reconnect();
20993fb14d0868594c78a777e805545209636814e223Martijn Coenen                            } catch (FormatException e) {
21003fb14d0868594c78a777e805545209636814e223Martijn Coenen                               // Create an intent anyway, without NDEF messages
21013fb14d0868594c78a777e805545209636814e223Martijn Coenen                               generateEmptyNdef = true;
2102232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                            }
21033fb14d0868594c78a777e805545209636814e223Martijn Coenen                        } else {
21043fb14d0868594c78a777e805545209636814e223Martijn Coenen                            generateEmptyNdef = true;
21053fb14d0868594c78a777e805545209636814e223Martijn Coenen                        }
2106232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
21073fb14d0868594c78a777e805545209636814e223Martijn Coenen                       if (generateEmptyNdef) {
21083fb14d0868594c78a777e805545209636814e223Martijn Coenen                           ndefMsgs = new NdefMessage[] { };
21093fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.addNdefTechnology(null,
21103fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedHandle(),
21113fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedLibNfcType(),
21123fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   nativeTag.getConnectedTechnology(),
21133fb14d0868594c78a777e805545209636814e223Martijn Coenen                                   supportedNdefLength, cardState);
21143fb14d0868594c78a777e805545209636814e223Martijn Coenen                           nativeTag.reconnect();
21153fb14d0868594c78a777e805545209636814e223Martijn Coenen                       }
21163fb14d0868594c78a777e805545209636814e223Martijn Coenen                    } // else, no NDEF on this tech, continue loop
21173fb14d0868594c78a777e805545209636814e223Martijn Coenen                } else {
21183fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // Connect failed, tag maybe lost. Try next handle
21193fb14d0868594c78a777e805545209636814e223Martijn Coenen                    // anyway.
2120232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                }
2121e08c8939be916c393a62b995b2dee438cb8cec2fMartijn Coenen            }
21223fb14d0868594c78a777e805545209636814e223Martijn Coenen            lastHandleScanned = handles[techIndex];
21233fb14d0868594c78a777e805545209636814e223Martijn Coenen            techIndex++;
2124232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen        }
21253fb14d0868594c78a777e805545209636814e223Martijn Coenen        if (ndefMsgs == null && foundFormattable) {
21263fb14d0868594c78a777e805545209636814e223Martijn Coenen            // Tag is not NDEF yet, and found a formattable target,
21273fb14d0868594c78a777e805545209636814e223Martijn Coenen            // so add formattable tech to tech list.
21283fb14d0868594c78a777e805545209636814e223Martijn Coenen            nativeTag.addNdefFormatableTechnology(
21293fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableHandle,
21303fb14d0868594c78a777e805545209636814e223Martijn Coenen                    formattableLibNfcType);
21313fb14d0868594c78a777e805545209636814e223Martijn Coenen        }
21323fb14d0868594c78a777e805545209636814e223Martijn Coenen
21333fb14d0868594c78a777e805545209636814e223Martijn Coenen        return ndefMsgs;
21343fb14d0868594c78a777e805545209636814e223Martijn Coenen    }
21353fb14d0868594c78a777e805545209636814e223Martijn Coenen
21363fb14d0868594c78a777e805545209636814e223Martijn Coenen
21373fb14d0868594c78a777e805545209636814e223Martijn Coenen    final class NfcServiceHandler extends Handler {
2138232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2139b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        @Override
2140b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        public void handleMessage(Message msg) {
2141f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           switch (msg.what) {
2142b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton           case MSG_MOCK_NDEF: {
2143b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               NdefMessage ndefMsg = (NdefMessage) msg.obj;
2144b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton               Tag tag = Tag.createMockTag(new byte[] { 0x00 },
2145b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new int[] { },
2146b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton                       new Bundle[] { });
214757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, "mock NDEF tag, starting corresponding activity");
214857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               Log.d(TAG, tag.toString());
214976a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly               mNfcDispatcher.dispatchTag(tag, new NdefMessage[] { ndefMsg });
215057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
215157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
215257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2153f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_NDEF_TAG:
2154ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Tag detected, notifying applications");
2155f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
2156232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
2157232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen
2158232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               if (ndefMsgs != null) {
215998eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                   nativeTag.startPresenceChecking();
2160232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   dispatchNativeTag(nativeTag, ndefMsgs);
2161232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen               } else {
2162232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   // No ndef found or connect failed, just try to reconnect and dispatch
2163232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   if (nativeTag.reconnect()) {
216498eb4249dcec63009b1839c005f0cf9048e1f7beMartijn Coenen                       nativeTag.startPresenceChecking();
21653fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                       dispatchNativeTag(nativeTag, null);
2166232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                   } else {
2167232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       Log.w(TAG, "Failed to connect to tag");
2168232eabb7c6f04506dbf272e06b115178311a57b9Martijn Coenen                       nativeTag.disconnect();
2169f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2170f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               }
2171f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
21723fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton
2173f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_CARD_EMULATION:
2174ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Card Emulation message");
2175f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               byte[] aid = (byte[]) msg.obj;
217649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               /* Send broadcast */
217749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               Intent aidIntent = new Intent();
217849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.setAction(ACTION_AID_SELECTED);
217949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               aidIntent.putExtra(EXTRA_AID, aid);
218049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               if (DBG) Log.d(TAG, "Broadcasting ACTION_AID_SELECTED");
218193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
2182f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2183f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2184f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_ACTIVATION:
2185f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               NativeP2pDevice device = (NativeP2pDevice) msg.obj;
2186f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2187f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.d(TAG, "LLCP Activation message");
2188f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2189f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2190ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
2191f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (device.doConnect()) {
2192f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Check Llcp compliancy */
2193f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doCheckLlcp()) {
2194f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           /* Activate Llcp Link */
2195f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           if (mManager.doActivateLlcp()) {
2196ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                               if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
2197663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               // Register P2P device
2198663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                               mObjectMap.put(device.getHandle(), device);
2199eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               activateLlcpLink();
2200eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           } else {
2201eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               /* should not happen */
2202eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
2203eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                               device.doDisconnect();
2204b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                           }
2205b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2206f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       } else {
2207ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
2208f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                           device.doDisconnect();
2209b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau                       }
2210eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                   } else {
22117f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
22127f5487be0414b1f92b41cc5f7b0b7db846d9b1c9Arnaud Ferir                       /* The polling loop should have been restarted in failing doConnect */
2213f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2214f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2215f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
2216ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                   if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
2217f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   /* Check Llcp compliancy */
2218f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   if (mManager.doCheckLlcp()) {
2219f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       /* Activate Llcp Link */
2220f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       if (mManager.doActivateLlcp()) {
2221ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                           if (DBG) Log.d(TAG, "Target Activate LLCP OK");
2222663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           // Register P2P device
2223663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           mObjectMap.put(device.getHandle(), device);
2224eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                           activateLlcpLink();
2225eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton                      }
22266f7fd8dbda9092e36e58273e843ae3e4a200e2ffJeff Hamilton                   } else {
2227ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                       Log.w(TAG, "checkLlcp failed");
2228f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                   }
2229b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau               }
2230f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2231f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2232f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_LLCP_LINK_DEACTIVATED:
2233eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               device = (NativeP2pDevice) msg.obj;
2234eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2235eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton               Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
2236663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau               synchronized (NfcService.this) {
2237663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   /* Check if the device has been already unregistered */
2238663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   if (mObjectMap.remove(device.getHandle()) != null) {
2239663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       /* Disconnect if we are initiator */
2240663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
2241663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "disconnecting from target");
2242663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           /* Restart polling loop */
2243663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           device.doDisconnect();
2244663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       } else {
2245663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                           if (DBG) Log.d(TAG, "not disconnecting from initiator");
2246663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                       }
2247663c0153d74ddbe8e8ec1f9f55780beafa2543faSylvain Fonteneau                   }
2248cdab1112486288ee6ccc9eb5c55456f9618f6b9cJeff Hamilton               }
2249eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton
2250f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Link LLCP activated */
2251f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent LlcpLinkIntent = new Intent();
2252f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
2253f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
2254f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly                       NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
2255ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
2256f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
2257f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2258f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
2259f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           case MSG_TARGET_DESELECTED:
2260f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               /* Broadcast Intent Target Deselected */
2261ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Target Deselected");
2262f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Intent TargetDeselectedIntent = new Intent();
2263f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
2264ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton               if (DBG) Log.d(TAG, "Broadcasting Intent");
2265f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
2266f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2267f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly
226857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_SHOW_MY_TAG_ICON: {
226957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
227057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
227157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
227257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
227357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
227457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
227557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           case MSG_HIDE_MY_TAG_ICON: {
227657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               StatusBarManager sb = (StatusBarManager) getSystemService(
227757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton                       Context.STATUS_BAR_SERVICE);
227857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               sb.removeIcon("nfc");
227957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton               break;
228057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton           }
228157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton
2282c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_ACTIVATED:{
2283c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
2284c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOnIntent = new Intent();
228549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
2286c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
228793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
2288c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2289c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2290c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2291c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           case MSG_SE_FIELD_DEACTIVATED:{
2292c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
2293c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               Intent eventFieldOffIntent = new Intent();
229449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly               eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
2295c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               if (DBG) Log.d(TAG, "Broadcasting Intent");
229693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton               mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
2297c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas               break;
2298c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas           }
2299c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas
2300f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           default:
2301f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               Log.e(TAG, "Unknown message received");
2302f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly               break;
2303f348bf5b21c5c39d7b3627327db1e61007d07539Nick Pelly           }
2304b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau        }
2305d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton
23063fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
23073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
23080c322dc2d942285bfcd9fe5c0bba1a5f36a967f5Jeff Hamilton                    nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
230910389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen            registerTagObject(nativeTag);
231076a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly            if (!mNfcDispatcher.dispatchTag(tag, msgs)) {
231110389c11abdae4c794082f6c51f11b28b422eddbMartijn Coenen                unregisterObject(nativeTag.getHandle());
23123fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton                nativeTag.disconnect();
23133fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton            }
23143fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton        }
2315b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    }
2316b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau
2317b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton    private NfcServiceHandler mHandler = new NfcServiceHandler();
231849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly
23197c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
2320fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks        @Override
2321275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks        protected Void doInBackground(Boolean... params) {
2322275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]);
2323275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2324275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            if (params != null && params.length > 0 && params[0]) {
2325161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2326275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (!mScreenUnlocked) {
2327275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = true;
2328275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2329275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2330275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring enable request");
2331275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2332161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
23337c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            } else {
2334533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.acquire();
2335161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                synchronized (NfcService.this) {
2336275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    if (mScreenUnlocked) {
2337275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        mScreenUnlocked = false;
2338275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        applyRouting();
2339275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        maybeDisconnectTarget();
2340275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    } else {
2341275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                        if (DBG) Log.d(TAG, "Ignoring disable request");
2342275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                    }
2343161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly                }
2344533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly                mWakeLock.release();
23457c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            }
23467c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly            return null;
23477c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly        }
23487c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly    }
23497c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly
23500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
23510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        @Override
23520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly        public void onReceive(Context context, Intent intent) {
2353eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton            if (intent.getAction().equals(
2354f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
2355ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton                if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
23560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly
2357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly                /* Restart polling loop for notification */
235849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly                applyRouting();
2359f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly
236065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
23617c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery enable in thread to protect against ANR when the
23627c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
23637c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
23647c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2365275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2366275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Only enable if the screen is unlocked. If the screen is locked
2367275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // Intent.ACTION_USER_PRESENT will be broadcast when the screen is
2368275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // unlocked.
2369275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                boolean enable = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure();
2370275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks
2371275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(enable);
237265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
23737c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // Perform discovery disable in thread to protect against ANR when the
23747c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // NFC stack wedges. This is *not* the correct way to fix this issue -
23757c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // configuration of the local NFC adapter should be very quick and should
23767c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly                // be safe on the main thread, and the NFC stack should not wedge.
2377275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.FALSE);
2378275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks            } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
2379275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                // The user has unlocked the screen. Enabled!
2380275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks                new EnableDisableDiscoveryTask().execute(Boolean.TRUE);
2381bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
2382a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                executeSeReset();
2383bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks            } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
23847a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
23857a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                if (dataRemoved) {
23867a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    Uri data = intent.getData();
23877a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    if (data == null) return;
23887a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    String packageName = data.getSchemeSpecificPart();
23897a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton
23907a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                    synchronized (NfcService.this) {
2391a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                        if (packageName.equals(mSePackageName)) {
2392a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly                            executeSeReset();
23937a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton                        }
2394bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                    }
2395bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks                }
2396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly            }
2397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly        }
2398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly    };
239974180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick}
2400