NfcService.java revision e008eba3b51c5303d52bf3e9e989dfd03b18435a
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 19f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.DeviceHostListener; 20e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenenimport com.android.nfc.DeviceHost.LlcpConnectionlessSocket; 214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.DeviceHost.LlcpServerSocket; 224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.DeviceHost.LlcpSocket; 23f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.NfcDepEndpoint; 24f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.TagEndpoint; 2581c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcManager; 2681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcSecureElement; 27d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 29275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 3005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 3231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 37483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenenimport android.content.pm.PackageInfo; 3893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 39d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 40d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 42f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 442094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4649d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 529d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 53aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5481c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 557c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 5650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 57b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 58b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 5949d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 60b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 61533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 624467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 63f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 6413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 65d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 66f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 67f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 6831949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 6957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 7031949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 7131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 723ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 7384e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 74c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamiltonimport java.util.List; 7531949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 763ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 7777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pellypublic class NfcService extends Application implements DeviceHostListener { 78bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 79bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 80c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 8176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 82fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 83d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 84fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 85c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** Regular NFC permission */ 86bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 87bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 88c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 89c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** NFC ADMIN permission - only for system apps */ 90bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 91bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 92bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 9377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 94f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 95416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 96416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 97416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 98416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 99416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 100416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 101a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 102fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final boolean PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE = true; 103fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 104b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 105b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 106b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 107b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 108b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 109b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 110c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 111c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1122c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1132c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1142c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 115b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 11631949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 11731949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 11831949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 11931949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 12031949217328bf2357ff044f0d18677fe588c790cNick Pelly 121fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Screen state, used by mScreenState 122fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_UNKNOWN = 0; 123fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_OFF = 1; 124fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_LOCKED = 2; 125fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_UNLOCKED = 3; 126fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 12749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1317efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 132fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** minimum screen state that enables NFC polling (discovery) */ 133fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; 134fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 135d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 136d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 137d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 138d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 139d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 14049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 14149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 14249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 14349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 14449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 14549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 14649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 14749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1482c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1492c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1502c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1512c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1522c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1532c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 1542c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 1552c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1562c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 1572c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 1582c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 1592c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 1602c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 16131949217328bf2357ff044f0d18677fe588c790cNick Pelly //TODO: dont hardcode this 16231949217328bf2357ff044f0d18677fe588c790cNick Pelly private static final byte[][] EE_WIPE_APDUS = { 16331949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 16431949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 16531949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 16631949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 16731949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 16831949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 16931949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 17031949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 17131949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 17231949217328bf2357ff044f0d18677fe588c790cNick Pelly }; 17349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 17449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 17549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 1760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 17749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 17849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 1790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 180d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 181d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 182d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 1832f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 184fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 185fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly HashSet<String> mSePackages = new HashSet<String>(); 186fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 187fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 188fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing 189fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling 19031949217328bf2357ff044f0d18677fe588c790cNick Pelly 19131949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 19231949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 19331949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 19431949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1952f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 1962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 19705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 1984a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 1990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 201533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly private PowerManager.WakeLock mWakeLock; 202d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 203d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 204d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 205d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 20677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2074a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2084a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2094a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 21031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 21131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 212c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfceeAccessControl mNfceeAccessControl; 2132ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 21476a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 215fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 216275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 217d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 219d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 22093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 221c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 22293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 22393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 224c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void enforceNfceeAdminPerm(String pkg) { 225c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (pkg == null) { 226c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException("caller must pass a package name"); 227c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 228c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 229c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) { 230c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH + 231c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton " denies NFCEE access to " + pkg); 232c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 23393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 23493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 235d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 236d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 237d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 241f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 247d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 252f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 254f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 255d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 257f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_CARD_EMULATION, aid); 258f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 260f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 261f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 262f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 263f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 271d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 273f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 274f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 275f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 276d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 277f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 278f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 279f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 280f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 281d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 282f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 283f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 284f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 285f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 286f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 287442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 288442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 289442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 290442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 291442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 292442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 293442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 294442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 295442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 296442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 297442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 298442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 299442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 300442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 301442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 3020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onCreate() { 3032f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onCreate(); 3042f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 3054a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 3064a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 307ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 3084a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 3092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 3102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 311d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 3130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mContext = this; 314f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost = new NativeNfcManager(this, this); 31574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 31677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager = new P2pLinkManager(mContext); 31777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mNfcDispatcher = new NfcDispatcher(this, mP2pLinkManager); 31824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 3190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas mSecureElement = new NativeNfcSecureElement(); 320eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 3210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 322c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl = new NfceeAccessControl(this); 323c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 324275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 3250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 32731949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3280b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 330fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 331275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 332fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 333275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 334fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = checkScreenState(); 335533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 336d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 338eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 33965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 34065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 341bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 342275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 34331949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 344275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 345bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 346bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter = new IntentFilter(); 347bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 348bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addDataScheme("package"); 349bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 350275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 3510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 35231949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 35331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 35431949217328bf2357ff044f0d18677fe588c790cNick Pelly 355d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 356d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 357d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 358d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 359d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mStartSound = mSoundPool.load(this, R.raw.start, 1); 360d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mEndSound = mSoundPool.load(this, R.raw.end, 1); 361d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mErrorSound = mSoundPool.load(this, R.raw.error, 1); 362d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 363d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 364d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 365d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 366d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 367d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 368d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 369d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 370d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 371d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 372d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 373d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 374d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 37531949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 37631949217328bf2357ff044f0d18677fe588c790cNick Pelly final ContentResolver resolver = mContext.getContentResolver(); 37731949217328bf2357ff044f0d18677fe588c790cNick Pelly final String airplaneModeRadios = Settings.System.getString(resolver, 37831949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_RADIOS); 37931949217328bf2357ff044f0d18677fe588c790cNick Pelly final String toggleableRadios = Settings.System.getString(resolver, 38031949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 38131949217328bf2357ff044f0d18677fe588c790cNick Pelly 38231949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 38331949217328bf2357ff044f0d18677fe588c790cNick Pelly airplaneModeRadios.contains(Settings.System.RADIO_NFC); 38431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 38531949217328bf2357ff044f0d18677fe588c790cNick Pelly toggleableRadios.contains(Settings.System.RADIO_NFC); 38631949217328bf2357ff044f0d18677fe588c790cNick Pelly 38731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 38831949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 38931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 39131949217328bf2357ff044f0d18677fe588c790cNick Pelly 392fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int checkScreenState() { 393fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (!mPowerManager.isScreenOn()) { 394fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_OFF; 395fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (mKeyguard.isKeyguardLocked()) { 396fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_LOCKED; 397fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 398fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_UNLOCKED; 399fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 400fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 401fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 40231949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 40331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 40431949217328bf2357ff044f0d18677fe588c790cNick Pelly * 40531949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 40631949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 40731949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 40831949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 40931949217328bf2357ff044f0d18677fe588c790cNick Pelly * 41031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 41131949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 41231949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 41331949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 41431949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 41531949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 41631949217328bf2357ff044f0d18677fe588c790cNick Pelly * 41731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 41831949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 41931949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 42031949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 42231949217328bf2357ff044f0d18677fe588c790cNick Pelly * 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 42731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 42831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 42931949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 43031949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 43131949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 43231949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 43331949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 43431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 43531949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 43631949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 43831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 43931949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 44031949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 44231949217328bf2357ff044f0d18677fe588c790cNick Pelly 4434467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4444467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4454467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4464467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4474467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4484467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4494467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4504467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4514467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 45531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 45731949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 4600fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 46131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 46231949217328bf2357ff044f0d18677fe588c790cNick Pelly !(mIsAirplaneSensitive && isAirplaneModeOn())) { 4630fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 4650fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 4660fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 4670fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 47431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 47631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 47731949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 47831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 47931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 480d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 481d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 482d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 48331949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 48431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 48531949217328bf2357ff044f0d18677fe588c790cNick Pelly 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 49131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 49231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 49331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 49431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 49531949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 49631949217328bf2357ff044f0d18677fe588c790cNick Pelly 49731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mDeviceHost.initialize()) { 49831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Error enabling NFC"); 49931949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 50031949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 50131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 50431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly 5060b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 50831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50931949217328bf2357ff044f0d18677fe588c790cNick Pelly 510d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 511d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 513fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 51531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 52131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 52231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 52331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 52731949217328bf2357ff044f0d18677fe588c790cNick Pelly 52831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 52931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 53031949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 53131949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 53231949217328bf2357ff044f0d18677fe588c790cNick Pelly WatchDogThread watchDog = new WatchDogThread(); 53331949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly 53577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 53631949217328bf2357ff044f0d18677fe588c790cNick Pelly 53731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 53831949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 53931949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 541fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly 5440b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly 55131949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly 553d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 554d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 55531949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[][]apdus = EE_WIPE_APDUS; 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!enableInternal()) { 565ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 567f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 568f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Executing SE wipe"); 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (handle == 0) { 57231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Could not open the secure element"); 57331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 57431949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57831949217328bf2357ff044f0d18677fe588c790cNick Pelly 57931949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 58031949217328bf2357ff044f0d18677fe588c790cNick Pelly 58131949217328bf2357ff044f0d18677fe588c790cNick Pelly for (byte[] cmd : apdus) { 582ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly byte[] resp = mSecureElement.doTransceive(handle, cmd); 583ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly if (resp == null) { 584ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 585ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly break; 586ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 58731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 58831949217328bf2357ff044f0d18677fe588c790cNick Pelly 58931949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.resetTimeouts(); 59031949217328bf2357ff044f0d18677fe588c790cNick Pelly mSecureElement.doDisconnect(handle); 59131949217328bf2357ff044f0d18677fe588c790cNick Pelly 59231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 59331949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 59431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59631949217328bf2357ff044f0d18677fe588c790cNick Pelly 59731949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 5982a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 59931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 60031949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 60131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60231949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 60331949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 60431949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 60531949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 60631949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(intent); 60731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61031949217328bf2357ff044f0d18677fe588c790cNick Pelly 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 61231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6170e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 618d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 619d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 620d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 621d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 622d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 623d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 624d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 625d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 626d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 627d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 628d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 629d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 630d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 631d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 632d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 633d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 634d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 635d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 636d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 637d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 6380e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 6392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly public void onTerminate() { 6402f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onTerminate(); 6412f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // NFC application is persistent, it should not be destroyed by framework 6420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly Log.wtf(TAG, "NFC service is under attack!"); 6430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6454a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 646fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 64893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 65031949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 65131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "denying enable() request (airplane mode)"); 65331949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 654f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 65631949217328bf2357ff044f0d18677fe588c790cNick Pelly 65731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 658f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 659f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 660fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6610e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean disable() throws RemoteException { 66293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 66431949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(false); 66531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 66631949217328bf2357ff044f0d18677fe588c790cNick Pelly 66731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 668f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 669f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 670fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6710b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 67231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 6739993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 67431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 675d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 676d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 677d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 6780b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 679d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 680d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 6810b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 68231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 68331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6840b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 6850b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 68631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 6870b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 68831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 68977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 690d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 691d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 692d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 693d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 694d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 695d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 6960b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 697d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 698d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 6990b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 70031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 70131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7020b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 7030b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 70431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7050b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 70631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 70777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 708d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 709d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 710d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 711d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 712d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 713d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7140b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 71524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 71605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 717a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 7180b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 7190b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 7200b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 7210b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 722ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 723a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 724a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 725a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 726a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 727a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 728a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 729a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 730a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 731a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 732a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 733a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 734a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 735a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 736a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 73724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 73824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 73924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 74024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 74124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 74249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 7430b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 7442094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7452094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 7462094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 7470b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundNdefPush(NdefMessage msg, INdefPushCallback callback) { 748ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7490b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.setNdefToSend(msg, callback); 750ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 751ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 752ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 7530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 754d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7550e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 7560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 758fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 759c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) { 760c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 76149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 7620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 7630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 764fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 76531949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 76631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 76731949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 76831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 76931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 77031949217328bf2357ff044f0d18677fe588c790cNick Pelly 77131949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 77231949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 77331949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 7740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 775c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 7760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 7774a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 778fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 779f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 780d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 781bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 782f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 783f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 78431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 785f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 786f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 787f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 788f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 789f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 790f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 791b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 792b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 79321545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 794b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 795f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 796f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 797fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 798f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 799f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 800f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 801fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 802ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 803d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 804bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 805f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 806f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 80731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 808f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 811f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 812f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 813b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 814b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 815f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 816ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 8171b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen if (technology == TagTechnology.NFC_B) { 8181b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen return ErrorCodes.ERROR_NOT_SUPPORTED; 8191b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen } 8201b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen 821ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 822ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 823ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 824ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 825ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 826ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 827ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 828ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 831fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 832aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 833aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 834aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 835f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 836aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 837aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 83831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 839aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 840aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 841aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 842aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 843f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 844aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 845aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 846aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 847aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 848aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 849aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 850aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 851aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 852aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 853aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 854aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 855b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 856d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 857bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 858f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 85931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 860f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 861f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 862f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 863f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 864f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 865f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 866b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 867f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 868f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 869f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 870f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 871fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 872f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public byte[] getUid(int nativeHandle) throws RemoteException { 873f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 874f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] uid; 875f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 876f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 87731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 878f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 879f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 881f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 882f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 884f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly uid = tag.getUid(); 885f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return uid; 886f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 887f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 888f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 889f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 890fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 891b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 892f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 893b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 894b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 89531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 896b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 897b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 898b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 899b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 900f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 901b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 902b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 903b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 904b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 905ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 906b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 907b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 908fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 909f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 910f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 91331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 9142c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 918f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 9193ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 9202c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 9212c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 922f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 92370bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 924f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 926fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9279d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 92897c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 929d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 930bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 931f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 932f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 934f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 93531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 937f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 940f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 942bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 943bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 944bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 945bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 9469d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 9479d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 948bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 949bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 950bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 951bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 952bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 953bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 954bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 955bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 956bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 961fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9623fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 963d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 964bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 965f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 966f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 96831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 973f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 975f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 976f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 978f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 990fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 992d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 993bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 994f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 99731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1002f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1004f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1007f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1009f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1015fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int getLastError(int nativeHandle) throws RemoteException { 1017f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton return(mDeviceHost.doGetLastError()); 1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1020fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 10223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1023f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1025fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10263fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 102703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 102803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1029f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 103003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 103103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 103231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 103303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 103403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 103503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 103603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1037f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 103803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 103903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 104003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 104103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1042f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 104303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1044f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 104503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 104603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1047f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 10490aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 10500aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 10510aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10520aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1053f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 10540aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10550aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 105631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 10580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1061f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 10630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 10670aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1068f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 10690aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10700aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10710aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10731b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 10743fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 10753fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10763fb14d0868594c78a777e805545209636814e223Martijn Coenen 1077f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 10783fb14d0868594c78a777e805545209636814e223Martijn Coenen 10793fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 108031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10813fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 10823fb14d0868594c78a777e805545209636814e223Martijn Coenen } 10833fb14d0868594c78a777e805545209636814e223Martijn Coenen 10843fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1085f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10863fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 10873fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 10883fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 10893fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 10903fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 10913fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 10923fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 10933fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 10943fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 10953fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 10963fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1097f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton NdefMessage[] msgs = tag.findAndReadNdef(); 10983fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 10993fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 11004a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 11013fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 11023fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11033fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 11043fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11053fb14d0868594c78a777e805545209636814e223Martijn Coenen 11061b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1107fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 11081b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1109f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1110fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1111fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1112fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1113fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1114fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1115dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1116dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1117dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1118358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1119358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1120358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1121358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1122358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1123358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1124358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1125dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1126dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1127dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1128f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 11291b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1130bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1131bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1132bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1133bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1134bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1135bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1136bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1137bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1138bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1139bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1140bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1141bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1142bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1143bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1144c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 114692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly void _nfcEeClose(int callingPid, IBinder binder) throws IOException { 1147dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1148dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1149dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1150dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 11510571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly synchronized (NfcService.this) { 115231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1153dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1154dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1155dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1156dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1157dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 115892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (callingPid != -1 && callingPid != mOpenEe.pid) { 1159dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1160dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 116192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (mOpenEe.binder != binder) { 116292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly throw new SecurityException("Wrong binder handle"); 116392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 1164dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 116592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly binder.unlinkToDeath(mOpenEe, 0); 1166f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1167dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mSecureElement.doDisconnect(mOpenEe.handle); 1168dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1169dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1170fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1171dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1172dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1173dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 11744a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 117549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 117649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 117749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 117849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 117949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 118049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeIoException(IOException e) { 118149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 118249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", -1); 118349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putString("m", e.getMessage()); 118449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 118549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1187bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1188c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle open(String pkg, IBinder b) throws RemoteException { 1189c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1190bd555ee64250126b60b24814120a2049943920caNick Pelly 119149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 119249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 119349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly _open(b); 119449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 119549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 119649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 11970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 119849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 119949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1201c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private void _open(IBinder b) throws IOException { 120249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 120331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 120449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC adapter is disabled"); 120549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 120649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 120749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE already open"); 120849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 121049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 121149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (handle == 0) { 121249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE failed to open"); 121349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1214f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1215ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 121692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle, b); 121749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 121849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 121949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 122049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 122149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 122284e1e0adc2516afd35ebab029a52e764e0490559Jason parks 122384e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 122484e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 122584e1e0adc2516afd35ebab029a52e764e0490559Jason parks for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 122684e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 122784e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 122849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1231bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 123292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public Bundle close(String pkg, IBinder binder) throws RemoteException { 1233c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1234c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 123549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 123649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 123792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(getCallingPid(), binder); 123849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 123949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 124049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 124249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 124349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12440bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1245bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1246c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle transceive(String pkg, byte[] in) throws RemoteException { 1247c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1248bd555ee64250126b60b24814120a2049943920caNick Pelly 124949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 125049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 125149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 125249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 125349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 125449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 125549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 125649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 125849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 125949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1261c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private byte[] _transceive(byte[] data) throws IOException { 126249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 126331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 126449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 126549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12660571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly if (mOpenEe == null) { 126749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 126849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 126949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 127049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 127149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 127449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mSecureElement.doTransceive(mOpenEe.handle, data); 12750bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1277bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1278c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public int getCardEmulationRoute(String pkg) throws RemoteException { 1279c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 128049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 12810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1283bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1284c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void setCardEmulationRoute(String pkg, int route) throws RemoteException { 1285c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 128649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 1287fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 12880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1289bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1290bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1291c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void authenticate(String pkg, byte[] token) throws RemoteException { 1292c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1293bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1294c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 12950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 129649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 129749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 129849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 129992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // binder handle used for DeathReceipient. Must keep 130092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // a reference to this, otherwise it can get GC'd and 130192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // the binder stub code might create a different BinderProxy 130292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // for the same remote IBinder, causing mismatched 130392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // link()/unlink() 130492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public IBinder binder; 130549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 130692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public OpenSecureElement(int pid, int handle, IBinder binder) { 130749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 130849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 130992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly this.binder = binder; 131049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1311bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 131249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 131349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 131492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly Log.i(TAG, "Tracked app " + pid + " died"); 131549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 13160bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 131792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(-1, binder); 1318dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 13190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 132192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly @Override 132292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public String toString() { 132392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=") 132492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly .append(pid).append(" handle=").append(handle).append("]").toString(); 132592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 13260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 132831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 132931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 133031949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1331e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1332aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1333aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 133431949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 13352edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean mWatchDogCanceled = false; 13362edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 13372edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 13382edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean slept = false; 13392edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly while (!slept) { 13402edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly try { 13412edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Thread.sleep(10000); 13422edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly slept = true; 13432edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } catch (InterruptedException e) { } 13442edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13452edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly synchronized (this) { 13462edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly if (!mWatchDogCanceled) { 13472edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly // Trigger watch-dog 13482edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Log.e(TAG, "Watch dog triggered"); 13492083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly mDeviceHost.doAbort(); 13502edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13512edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13522edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13532edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 13542edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly mWatchDogCanceled = true; 13552edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13562edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13572edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 1358fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1359fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1360fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1361fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1362e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 1363e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (!isNfcEnabled() || mOpenEe != null) { 1364fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // PN544 cannot be reconfigured while EE is open 1365e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1366e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1367fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1368fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE && mScreenState == SCREEN_STATE_OFF) { 1369fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /* TODO undo this after the LLCP stack is fixed. 1370fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Use a different sequence when turning the screen off to 1371fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * workaround race conditions in pn544 libnfc. The race occurs 1372fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * when we change routing while there is a P2P target connect. 1373fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * The async LLCP callback will crash since the routing code 1374fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * is overwriting globals it relies on. 1375fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1376fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (POLLING_MODE > SCREEN_STATE_OFF) { 1377fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfcPollingEnabled) { 1378fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C OFF, disconnect"); 1379fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = false; 1380fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.disableDiscovery(); 1381fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly maybeDisconnectTarget(); 1382fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1383fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1384e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1385fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfceeRouteEnabled) { 1386fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1387fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1388fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.doDeselectSecureElement(); 1389fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1390fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1391fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return; 1392fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1393fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1394fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // configure NFC-EE routing 1395fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (mScreenState >= SCREEN_STATE_ON_LOCKED && 1396fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1397fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || !mNfceeRouteEnabled) { 1398fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE ON"); 1399fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = true; 1400e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doSelectSecureElement(); 1401fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1402fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 1403fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfceeRouteEnabled) { 1404fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1405fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1406e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doDeselectSecureElement(); 1407e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1408fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1409fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1410fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // configure NFC-C polling 1411fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (mScreenState >= POLLING_MODE) { 1412fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || !mNfcPollingEnabled) { 1413fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C ON"); 1414fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = true; 1415fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.enableDiscovery(); 1416fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1417221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } else { 1418fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfcPollingEnabled) { 1419fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C OFF"); 1420fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = false; 1421fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.disableDiscovery(); 1422fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1423221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 142465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 142565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 142665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 14272436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 142831949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 142931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1430a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1431a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 143231949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 143331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 143431949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 143531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 143631949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 143731949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 143831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 143931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 144031949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 144131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 144231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 144331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 144431949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 144531949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 144631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 144731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 144831949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 144931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 145031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 145131949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 145231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 145331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 145431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1455bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1456bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1457bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1458bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1459bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 146031949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 146131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 146231949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 146331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 146431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 14652f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 146631949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 14670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1468f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1469f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 147031949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 147131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 147231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1473f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1474b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1475b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 147631949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 147731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 147831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 147931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1480f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1482d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 14834a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1484c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 14854a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1486d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1487d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1488d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 1489e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap) 1490e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 1491e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap); 1492e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1493e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 1494e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen /** For use by code in this process */ 14954a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1496c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 14974a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1498d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1499d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 150057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1501b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 150257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 150357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1504b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1505b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1506b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1507b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1508b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1509b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1510b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 15113fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1512b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1513b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 151431949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 151531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 151631949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 151731949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 151831949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 151931949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 152031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 152131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 152231949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 152331949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 152431949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 152531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 152631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 152731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag, 152831949217328bf2357ff044f0d18677fe588c790cNick Pelly new NdefMessage[] { ndefMsg }); 152931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 1530d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 153177d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 1532d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 153331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 153431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 153531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 153657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 153731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 153831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 153931949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 1540d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_START); 154131949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage[] ndefMsgs = tag.findAndReadNdef(); 1542c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 154331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (ndefMsgs != null) { 154431949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 154531949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, ndefMsgs); 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 154731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 154831949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 154931949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, null); 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1552d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly 155731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 155831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 155931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 156031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 156131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 156231949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 156431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 156514a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 156631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 156731949217328bf2357ff044f0d18677fe588c790cNick Pelly 156831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 156931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 157031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 157131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 157231949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 157331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 157414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 157531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 157631949217328bf2357ff044f0d18677fe588c790cNick Pelly 157731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 157831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 157931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 158031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 158131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 158231949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 158331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 158431949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 158531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 158631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 158714a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 158831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 158931949217328bf2357ff044f0d18677fe588c790cNick Pelly 159031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 159131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 159231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 159331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 159431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 159531949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 159631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 159731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 159831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 159931949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 160031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 160131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 160214a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 160331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 1604c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 160531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 160631949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 160731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 160831949217328bf2357ff044f0d18677fe588c790cNick Pelly 160931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 161031949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 161131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 161231949217328bf2357ff044f0d18677fe588c790cNick Pelly 161331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 161431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 161531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 161631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 161731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 161831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 161931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 162031949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 162131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 162231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 162331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 162431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 162531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 162631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 162731949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 162831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 162931949217328bf2357ff044f0d18677fe588c790cNick Pelly 163077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 163131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 163231949217328bf2357ff044f0d18677fe588c790cNick Pelly 163331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 163431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 163531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 163631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 163731949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 163831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 163931949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 164031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 164131949217328bf2357ff044f0d18677fe588c790cNick Pelly 164231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 164331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 164431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 164531949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 164614a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 164731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 164831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 164931949217328bf2357ff044f0d18677fe588c790cNick Pelly 165031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 165131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 165231949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 165331949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 165414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 165531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 165631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 165731949217328bf2357ff044f0d18677fe588c790cNick Pelly 165831949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 165931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 166031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 166131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1662b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1663d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 166414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 1665c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton PackageManager pm = getPackageManager(); 166614a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1667c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 1668c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Resume app switches so the receivers can start activites without delay 1669c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfcDispatcher.resumeAppSwitches(); 1670c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 1671483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenen List<PackageInfo> packages = pm.getInstalledPackages(0); 1672483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenen for (PackageInfo pkg : packages) { 1673483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenen if (pkg != null && pkg.applicationInfo != null) { 1674483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 1675483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenen intent.setPackage(pkg.packageName); 1676c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.sendBroadcast(intent); 1677c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1678c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1679c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 168014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 168114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 1682d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1683d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1684d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1685d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1686d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1687d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1688d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1689d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1690d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1691d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1692d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 169331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 169431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1696d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 169777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1698d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1699d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1700d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1701d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1702d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1703d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1704d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1705d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1706d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1707d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1708d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1709d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1710d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1711d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1712d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1713d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1714d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1715d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1716d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1717d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1718d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1719d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1720d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1721d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 172231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 172331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 172431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1725d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 172677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1727d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1728d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1729d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1730d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1731d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1732d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1733d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1734d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1735d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1736d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1737f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) { 1738f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1739f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1740f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 174176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly if (!mNfcDispatcher.dispatchTag(tag, msgs)) { 1742f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1743d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 1744d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1745d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 17463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 17473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1748b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1749b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1750b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 175149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1752fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 1753fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1754fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 1755fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 1756fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 1757fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 1758fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1759fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 1760161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1761fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 1762fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1763fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean needWakelock = mScreenState == SCREEN_STATE_OFF; 1764fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (needWakelock) { 1765fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock.acquire(); 1766fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1767fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(false); 1768fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (needWakelock) { 1769fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock.release(); 1770161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1771fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 17727c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 17737c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 17747c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 17757c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 17760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 17770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 17780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (action.equals( 1781f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 1782fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Perform applyRouting() in AsyncTask to serialize blocking calls 1783fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly new ApplyRoutingTask().execute(); 1784fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_SCREEN_ON) 1785fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly || action.equals(Intent.ACTION_SCREEN_OFF) 1786fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly || action.equals(Intent.ACTION_USER_PRESENT)) { 1787fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Perform applyRouting() in AsyncTask to serialize blocking calls 1788fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int screenState = SCREEN_STATE_OFF; 1789fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1790fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = SCREEN_STATE_OFF; 1791fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1792fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = mKeyguard.isKeyguardLocked() ? 1793fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED; 1794fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1795fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = SCREEN_STATE_ON_UNLOCKED; 1796fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1797fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 179831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 179931949217328bf2357ff044f0d18677fe588c790cNick Pelly EnableDisableTask eeWipeTask = new EnableDisableTask(); 180031949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.execute(TASK_EE_WIPE); 180131949217328bf2357ff044f0d18677fe588c790cNick Pelly try { 180231949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.get(); // blocks until EE wipe is complete 180331949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (ExecutionException e) { 180431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 180531949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (InterruptedException e) { 180631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 180731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 180831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 1809c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Clear the NFCEE access cache in case a UID gets recycled 1810c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.invalidateCache(); 1811c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 18127a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 18137a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (dataRemoved) { 18147a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton Uri data = intent.getData(); 18157a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (data == null) return; 18167a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton String packageName = data.getSchemeSpecificPart(); 18177a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 18187a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton synchronized (NfcService.this) { 181984e1e0adc2516afd35ebab029a52e764e0490559Jason parks if (mSePackages.contains(packageName)) { 182031949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_EE_WIPE); 182184e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.remove(packageName); 18227a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 1823bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1824bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 182531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 182631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 182731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 182831949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 182931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 183031949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 183131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 183231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 183331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 183431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 183531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 183631949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 183731949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 183831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 183931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1840f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1841f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1842f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 184331949217328bf2357ff044f0d18677fe588c790cNick Pelly 184431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 184531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 184631949217328bf2357ff044f0d18677fe588c790cNick Pelly return Settings.System.getInt(mContext.getContentResolver(), 184731949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_ON, 0) == 1; 184831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 184931949217328bf2357ff044f0d18677fe588c790cNick Pelly 1850fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** for debugging only - no i18n */ 185131949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 185231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 185331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 185431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 185531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 185631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 185731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 185831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 185931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 186031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 186131949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 186231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 186331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 186431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 186531949217328bf2357ff044f0d18677fe588c790cNick Pelly 1866fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** For debugging only - no i18n */ 1867fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static String screenStateToString(int screenState) { 1868fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly switch (screenState) { 1869fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_OFF: 1870fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "OFF"; 1871fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_LOCKED: 1872fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_LOCKED"; 1873fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_UNLOCKED: 1874fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_UNLOCKED"; 1875fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly default: 1876fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "UNKNOWN"; 1877fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1878fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1879fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 188031949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 188150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 188250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 188350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 188450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 188550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 188650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 188750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 188850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 188931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 189031949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 18910b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 1892fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mScreenState=" + screenStateToString(mScreenState)); 1893fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled); 1894fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled); 189531949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 189631949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 189792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly pw.println("mOpenEe=" + mOpenEe); 189877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 1899c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.dump(fd, pw, args); 190056f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 1901c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 190231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 190331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 190474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 1905