NfcService.java revision 37058bf7b59def2f9a565ae5b16aae54e80e9e95
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; 2543f2fa7ad4c72ef4849f2d2b78a963c1925c63a3Nick Pellyimport com.android.nfc.handover.HandoverManager; 2681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcManager; 2781c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcSecureElement; 28d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 30275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 3105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3213d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 3331949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 38483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenenimport android.content.pm.PackageInfo; 3993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 40d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 41d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 423fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 452094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4749d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 539d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 54aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5581c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 567c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 5750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 58b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 59b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 6049d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 61b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 62533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 634467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 64f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 6513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 66d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 67f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 68f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 6931949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 7057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 7131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 7231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 733ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 7484e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 75c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamiltonimport java.util.List; 7631949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 773ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 7877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pellypublic class NfcService extends Application implements DeviceHostListener { 79bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 80bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 81c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 8276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 83fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 84d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 85fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 86c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** Regular NFC permission */ 87bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 88bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 89c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 90c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** NFC ADMIN permission - only for system apps */ 91bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 92bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 93bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 9477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 95f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 96416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 97416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 98416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 99416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 100416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 101416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1021668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 103a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 104fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final boolean PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE = true; 105fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 106b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 107b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 108b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 109b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 110b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 111b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 112c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 113c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1142c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1152c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1162c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 11831949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 11931949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 12031949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 12131949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 12231949217328bf2357ff044f0d18677fe588c790cNick Pelly 123fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Screen state, used by mScreenState 124fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_UNKNOWN = 0; 125fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_OFF = 1; 126fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_LOCKED = 2; 127fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_UNLOCKED = 3; 128fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 13149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 13249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1337efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 134fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** minimum screen state that enables NFC polling (discovery) */ 135fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; 136fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 137d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 138d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 139d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 140d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 141d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 14249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 14349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 14449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 14549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 14649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 14749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 14849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 14949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1502c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1512c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1522c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1532c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1542c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1552c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 1562c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 1572c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1582c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 1592c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 1602c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 1612c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 1622c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 16331949217328bf2357ff044f0d18677fe588c790cNick Pelly //TODO: dont hardcode this 16431949217328bf2357ff044f0d18677fe588c790cNick Pelly private static final byte[][] EE_WIPE_APDUS = { 16531949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 16631949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 16731949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 16831949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 16931949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 17031949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 17131949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 17231949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 17331949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 17431949217328bf2357ff044f0d18677fe588c790cNick Pelly }; 17549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 17649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 17749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 1780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 17949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 18049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 1810bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 182d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 183d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 184d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 1852f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 186fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 187fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly HashSet<String> mSePackages = new HashSet<String>(); 188fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 189fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 190fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing 191fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling 192e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 19331949217328bf2357ff044f0d18677fe588c790cNick Pelly 19431949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 19531949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 19631949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 19731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 1992f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 20005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 2014a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2030e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 204533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly private PowerManager.WakeLock mWakeLock; 205d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 206d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 207d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 208d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 20977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2104a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2114a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2124a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 21331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 21431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 215c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfceeAccessControl mNfceeAccessControl; 2162ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 21776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 218fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 219275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 220d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 221d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 222d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 22393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 224c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 22593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 22693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 227c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void enforceNfceeAdminPerm(String pkg) { 228c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (pkg == null) { 229c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException("caller must pass a package name"); 230c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 231c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 232c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) { 233c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH + 234c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton " denies NFCEE access to " + pkg); 235c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 23693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 23793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 238d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 239d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 240d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 247f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 250d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 252f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 254f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 255f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 257f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 258d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 260f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_CARD_EMULATION, aid); 261f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 262f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 263f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 271f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 273f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 274d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 275f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 277f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 278f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 279d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 280f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 281f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 282f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 283f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 284d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 285f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 286f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 287f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 288f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 289f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 290442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 291442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 292442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 293442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 294442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 295442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 296442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 297442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 298442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 299442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 300442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 301442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 302442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 303442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 304442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 3050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onCreate() { 3062f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onCreate(); 3072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 3084a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 3094a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 310ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 3114a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 3122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 3132f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 314d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 315d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 3160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mContext = this; 317f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost = new NativeNfcManager(this, this); 31874180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 31943f2fa7ad4c72ef4849f2d2b78a963c1925c63a3Nick Pelly HandoverManager handoverManager = new HandoverManager(mContext); 32043f2fa7ad4c72ef4849f2d2b78a963c1925c63a3Nick Pelly mNfcDispatcher = new NfcDispatcher(this, handoverManager); 32143f2fa7ad4c72ef4849f2d2b78a963c1925c63a3Nick Pelly mP2pLinkManager = new P2pLinkManager(mContext, handoverManager); 32224dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 32337058bf7b59def2f9a565ae5b16aae54e80e9e95Sunil Jogi mSecureElement = new NativeNfcSecureElement(mContext); 324eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 3250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 326c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl = new NfceeAccessControl(this); 327c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 328275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 3290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 33131949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3320b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 334fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 335275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 336fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 337275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 338fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = checkScreenState(); 339533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 340d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 342eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 34365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 34465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 345bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 346275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 347e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 348e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 34931949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 350275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 351bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 352bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter = new IntentFilter(); 353e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen filter.addAction(Intent.ACTION_PACKAGE_ADDED); 354bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 355bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addDataScheme("package"); 356bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 357275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 3580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 359e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 360e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 36131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 36231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 36331949217328bf2357ff044f0d18677fe588c790cNick Pelly 364d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 365d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 366d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 367d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 368d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mStartSound = mSoundPool.load(this, R.raw.start, 1); 369d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mEndSound = mSoundPool.load(this, R.raw.end, 1); 370d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mErrorSound = mSoundPool.load(this, R.raw.error, 1); 371d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 372d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 373d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 374d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 375d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 376d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 377d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 378d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 379d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 380d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 381d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 382d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 383d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 38431949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 38531949217328bf2357ff044f0d18677fe588c790cNick Pelly final ContentResolver resolver = mContext.getContentResolver(); 38631949217328bf2357ff044f0d18677fe588c790cNick Pelly final String airplaneModeRadios = Settings.System.getString(resolver, 38731949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_RADIOS); 38831949217328bf2357ff044f0d18677fe588c790cNick Pelly final String toggleableRadios = Settings.System.getString(resolver, 38931949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly 39131949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 39231949217328bf2357ff044f0d18677fe588c790cNick Pelly airplaneModeRadios.contains(Settings.System.RADIO_NFC); 39331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 39431949217328bf2357ff044f0d18677fe588c790cNick Pelly toggleableRadios.contains(Settings.System.RADIO_NFC); 39531949217328bf2357ff044f0d18677fe588c790cNick Pelly 39631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 39731949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 39831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 39931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 40031949217328bf2357ff044f0d18677fe588c790cNick Pelly 401e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen void updatePackageCache() { 402e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen PackageManager pm = getPackageManager(); 403e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen List<PackageInfo> packages = pm.getInstalledPackages(0); 404e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (this) { 405e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mInstalledPackages = packages; 406e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 407e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 408e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 409fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int checkScreenState() { 410fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (!mPowerManager.isScreenOn()) { 411fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_OFF; 412fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (mKeyguard.isKeyguardLocked()) { 413fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_LOCKED; 414fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 415fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_UNLOCKED; 416fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 417fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 418fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 41931949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 42031949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly * 42231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly * 42731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 42831949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 42931949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 43031949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 43131949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 43231949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 43331949217328bf2357ff044f0d18677fe588c790cNick Pelly * 43431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 43531949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 43631949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 43831949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 43931949217328bf2357ff044f0d18677fe588c790cNick Pelly * 44031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 44231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 44331949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 44431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 44531949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 44631949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 44731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 44831949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 44931949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 45031949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 45131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 45531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 45731949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly 4604467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4614467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4624467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4634467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4644467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4654467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4664467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4674467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4684467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 47431949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 47531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 47631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 4770fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 4781668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 47931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 4801668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 4810fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 48231949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 4830fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 4840fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 4850fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 49131949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 49231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 49331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 49431949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 49531949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 49631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 49731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 498d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 499d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 500d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 50131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly 50431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 50631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 50831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 50931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 51031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 51131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 51331949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly 5150c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mDeviceHost.initialize()) { 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Error enabling NFC"); 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52131949217328bf2357ff044f0d18677fe588c790cNick Pelly 52231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 52331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly 5250b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 52731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52831949217328bf2357ff044f0d18677fe588c790cNick Pelly 529d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 530d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 53131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 5320c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 533fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 53531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 53631949217328bf2357ff044f0d18677fe588c790cNick Pelly 53731949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 53831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 53931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 54131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 54431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 55131949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly WatchDogThread watchDog = new WatchDogThread(); 55331949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 55431949217328bf2357ff044f0d18677fe588c790cNick Pelly 55577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 561fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly 5640b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 56531949217328bf2357ff044f0d18677fe588c790cNick Pelly 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 57231949217328bf2357ff044f0d18677fe588c790cNick Pelly 573d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 574d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 57631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly 57831949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 57931949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 58031949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[][]apdus = EE_WIPE_APDUS; 58131949217328bf2357ff044f0d18677fe588c790cNick Pelly 58231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 58331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 58431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!enableInternal()) { 585ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 58631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 587f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 588f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 58931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Executing SE wipe"); 59031949217328bf2357ff044f0d18677fe588c790cNick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 59131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (handle == 0) { 59231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Could not open the secure element"); 59331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 59431949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 59531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 59731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59831949217328bf2357ff044f0d18677fe588c790cNick Pelly 59931949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 60031949217328bf2357ff044f0d18677fe588c790cNick Pelly 60131949217328bf2357ff044f0d18677fe588c790cNick Pelly for (byte[] cmd : apdus) { 602ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly byte[] resp = mSecureElement.doTransceive(handle, cmd); 603ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly if (resp == null) { 604ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 605ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly break; 606ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 60731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.resetTimeouts(); 61031949217328bf2357ff044f0d18677fe588c790cNick Pelly mSecureElement.doDisconnect(handle); 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly 61231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61631949217328bf2357ff044f0d18677fe588c790cNick Pelly 61731949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 6182a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 61931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 62031949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 62331949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(intent); 62731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 63031949217328bf2357ff044f0d18677fe588c790cNick Pelly 63131949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 63231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 63331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 63431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 63531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 638d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 639d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 640d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 641d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 642d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 643d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 644d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 645d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 646d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 647d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 648d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 649d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 650d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 651d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 652d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 653d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 654d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 655d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 656d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 657d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 6580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 6592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly public void onTerminate() { 6602f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onTerminate(); 6612f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // NFC application is persistent, it should not be destroyed by framework 6620e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly Log.wtf(TAG, "NFC service is under attack!"); 6630e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6640e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6654a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 666fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6670e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 66893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6690e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 67031949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 6711668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 6721668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 6731668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 6741668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 6751668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 6761668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 6771668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 6781668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 6791668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 680f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 68131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 68231949217328bf2357ff044f0d18677fe588c790cNick Pelly 68331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 684f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 685f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 686fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 687290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 68893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 690290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 691290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 692290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 693290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 69431949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 69531949217328bf2357ff044f0d18677fe588c790cNick Pelly 69631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 697f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 698f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 699fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 7000b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 70131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 7029993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 70331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 704d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 705d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 706d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7070b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 708d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 709d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 7100b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 71131949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 71231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7130b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 7140b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 71531949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7160b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 71731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 71877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 719d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 720d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 721d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 722d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 723d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 724d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7250b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 726d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 727d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 7280b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 72931949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 73031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7310b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 7320b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 73331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7340b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 73531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 73677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 737d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 738d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 739d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 740d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 741d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 742d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7430b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 74424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 74505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 746a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 7470b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 7480b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 7490b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 7500b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 751ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 752a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 753a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 754a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 755a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 756a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 757a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 758a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 759a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 760a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 761a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 762a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 763a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 764a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 765a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 76624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 76724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 76824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 76924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 77024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 77149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 7720b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 7732094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7742094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 7752094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 776c96f982f8c0fa061701143a27395acf3b24dfb54Nick Pelly public void setNdefPushCallback(INdefPushCallback callback) { 777ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 778c96f982f8c0fa061701143a27395acf3b24dfb54Nick Pelly mP2pLinkManager.setNdefCallback(callback); 779ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 780ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 781ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 7820e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 7830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 7840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 786fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 787c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) { 788c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 78949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 7900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 7910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 792fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 79331949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 79431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 79531949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 79631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79831949217328bf2357ff044f0d18677fe588c790cNick Pelly 79931949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 80031949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 80131949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 8020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 803391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 804391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 805ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 806391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly enforceAdminPerm(mContext); 807ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 808391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 8090c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 8100c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 8110c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 8120c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen enforceAdminPerm(mContext); 8130c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 8140c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 8150c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 8160c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.disableDiscovery(); 8170c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.enableDiscovery(); 8180c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 819c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 8200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 8214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 822fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 823f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 824d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 825bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 826f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 827f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 82831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 832f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 833f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 834f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 835b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 836b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 83721545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 838b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 839f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 840f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 841fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 842f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 843f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 844f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 845fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 846ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 847d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 848bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 849f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 850f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 85131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 852f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 853f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 854f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 855f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 856f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 857b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 858b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 859f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 860ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 861cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 862cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 863cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 864cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 8651b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen if (technology == TagTechnology.NFC_B) { 8661b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen return ErrorCodes.ERROR_NOT_SUPPORTED; 8671b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen } 8681b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen 869ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 870ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 871ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 872ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 873ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 874ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 875ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 876ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 877f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 878f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 879fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 880aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 881aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 882aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 883f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 884aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 885aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 88631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 887aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 888aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 889aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 890aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 891f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 892aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 893aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 894aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 895aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 896aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 897aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 898aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 899aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 900aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 901aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 902aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 903b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 904d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 905bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 906f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 90731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 909f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 912f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 914b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 915f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 916f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 918f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 919fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 920b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 921f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 922b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 923b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 92431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 925b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 926b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 927b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 928b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 929f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 930b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 931b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 932b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 933b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 934ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 935b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 936b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 937fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 939182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 940182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 941f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 942f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 94431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 9452c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 949f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 9503ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 9512c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 9522c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 95470bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 957fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9589d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 95997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 960d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 961bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 962f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 96631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 971f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 973bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 974bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 975bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 976bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 9779d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 9789d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 979bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 980bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 981bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 982bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 983bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 984bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 985bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 986bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 987bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 990f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 992fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 994d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 995bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 996f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 99931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1004f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1005f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1006f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1007f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1008f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1009f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1021fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1023d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1024bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1025f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 102831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1033f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1034f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1038791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1039791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1040f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1042f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1045f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1046f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1047f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1048fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 10503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1053fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 105503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 105603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1057f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 105803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 105903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 106031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 106103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 106203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 106303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 106403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1065f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 106603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 106703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 106803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 106903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1070f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 107103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1072f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 107303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 107403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1075f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1076f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 10770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 10780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 10790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1081f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 10820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 108431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 10860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1089f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 10910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 10950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1096f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 10970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10980aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10990aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 11000aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 11011b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 11023fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 11033fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 11043fb14d0868594c78a777e805545209636814e223Martijn Coenen 1105f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 11063fb14d0868594c78a777e805545209636814e223Martijn Coenen 11073fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 110831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 11093fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 11103fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11113fb14d0868594c78a777e805545209636814e223Martijn Coenen 11123fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1113f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 11143fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 11153fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 11163fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 11173fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 11183fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 11193fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 11203fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 11213fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 11223fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 11233fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 11243fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1125391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 11263fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 11273fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 11284a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 11293fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 11303fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11313fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 11323fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11333fb14d0868594c78a777e805545209636814e223Martijn Coenen 11341b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1135fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 11361b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1137f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1138fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1139fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1140fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1141fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1142fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1143dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1144dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1145dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1146358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1147358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1148358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1149358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1150358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1151358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1152358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1153dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1154dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1155dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1156f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 11571b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1158bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1159bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1160bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1161bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1162bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1163bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1164bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1165bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1166bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1167bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1168ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1169ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1170ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1171ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1172ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1173c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 117592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly void _nfcEeClose(int callingPid, IBinder binder) throws IOException { 1176dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1177dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1178dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1179dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 11800571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly synchronized (NfcService.this) { 118131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1182dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1183dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1184dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1185dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1186dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 118792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (callingPid != -1 && callingPid != mOpenEe.pid) { 1188dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1189dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 119092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (mOpenEe.binder != binder) { 119192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly throw new SecurityException("Wrong binder handle"); 119292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 1193dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 119492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly binder.unlinkToDeath(mOpenEe, 0); 1195f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1196dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mSecureElement.doDisconnect(mOpenEe.handle); 1197dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1198dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1199fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1200dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1201dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1202dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 12034a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 120449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 120549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 120649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 120749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 120849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 120949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeIoException(IOException e) { 121049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 121149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", -1); 121249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putString("m", e.getMessage()); 121349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 121449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12150bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1216bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1217c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle open(String pkg, IBinder b) throws RemoteException { 1218c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1219bd555ee64250126b60b24814120a2049943920caNick Pelly 122049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 122149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 122249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly _open(b); 122349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 122449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 122549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 122749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 122849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12290bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1230c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private void _open(IBinder b) throws IOException { 123149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 123231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 123349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC adapter is disabled"); 123449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 123549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 123649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE already open"); 123749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 123949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 124049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (handle == 0) { 124149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE failed to open"); 124249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1244ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 124592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle, b); 124649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 124749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 124849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 124949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 125049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 125184e1e0adc2516afd35ebab029a52e764e0490559Jason parks 125284e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 125384e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 125484e1e0adc2516afd35ebab029a52e764e0490559Jason parks for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 125584e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 125684e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 125749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1260bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 126192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public Bundle close(String pkg, IBinder binder) throws RemoteException { 1262c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1263c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 126449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 126549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 126692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(getCallingPid(), binder); 126749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 126849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 126949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 127149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 127249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1274bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1275c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle transceive(String pkg, byte[] in) throws RemoteException { 1276c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1277bd555ee64250126b60b24814120a2049943920caNick Pelly 127849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 127949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 128049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 128149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 128249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 128349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 128449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 128549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12860bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 128749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 128849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1290c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private byte[] _transceive(byte[] data) throws IOException { 129149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 129231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 129349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 129449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12950571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly if (mOpenEe == null) { 129649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 129749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 129849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 129949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 130049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 13010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 130349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mSecureElement.doTransceive(mOpenEe.handle, data); 13040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1306bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1307c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public int getCardEmulationRoute(String pkg) throws RemoteException { 1308c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 130949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 13100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1312bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1313c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void setCardEmulationRoute(String pkg, int route) throws RemoteException { 1314c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 131549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 1316fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 13170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1318bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1319bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1320c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void authenticate(String pkg, byte[] token) throws RemoteException { 1321c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1322bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1323c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 13240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 132549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 132649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 132749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 132892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // binder handle used for DeathReceipient. Must keep 132992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // a reference to this, otherwise it can get GC'd and 133092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // the binder stub code might create a different BinderProxy 133192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // for the same remote IBinder, causing mismatched 133292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // link()/unlink() 133392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public IBinder binder; 133449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 133592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public OpenSecureElement(int pid, int handle, IBinder binder) { 133649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 133749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 133892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly this.binder = binder; 133949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1340bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 134149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 134249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 134392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly Log.i(TAG, "Tracked app " + pid + " died"); 134449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 13450bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 134692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(-1, binder); 1347dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 13480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13490bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 135092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly @Override 135192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public String toString() { 135292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=") 135392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly .append(pid).append(" handle=").append(handle).append("]").toString(); 135492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 13550bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 13579a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 13589a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 13599a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 13609a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13619a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13629a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 136331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 136431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 136531949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1366e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1367aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1368aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 136931949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 13702edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean mWatchDogCanceled = false; 13712edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 13722edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 13732edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean slept = false; 13742edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly while (!slept) { 13752edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly try { 13762edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Thread.sleep(10000); 13772edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly slept = true; 13782edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } catch (InterruptedException e) { } 13792edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13802edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly synchronized (this) { 13812edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly if (!mWatchDogCanceled) { 13822edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly // Trigger watch-dog 13832edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Log.e(TAG, "Watch dog triggered"); 13842083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly mDeviceHost.doAbort(); 13852edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13862edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13872edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13882edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 13892edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly mWatchDogCanceled = true; 13902edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13912edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13922edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 1393fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1394fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1395fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1396fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1397e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 13989a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) { 1399fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // PN544 cannot be reconfigured while EE is open 1400e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1401e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1402fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1403fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE && mScreenState == SCREEN_STATE_OFF) { 1404fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /* TODO undo this after the LLCP stack is fixed. 1405fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Use a different sequence when turning the screen off to 1406fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * workaround race conditions in pn544 libnfc. The race occurs 1407fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * when we change routing while there is a P2P target connect. 1408fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * The async LLCP callback will crash since the routing code 1409fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * is overwriting globals it relies on. 1410fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1411fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (POLLING_MODE > SCREEN_STATE_OFF) { 1412fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfcPollingEnabled) { 1413fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C OFF, disconnect"); 1414fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = false; 1415fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.disableDiscovery(); 1416fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly maybeDisconnectTarget(); 1417fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1418fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1419e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1420fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfceeRouteEnabled) { 1421fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1422fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1423fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.doDeselectSecureElement(); 1424fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1425fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1426fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return; 1427fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1428fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1429fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // configure NFC-EE routing 1430fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (mScreenState >= SCREEN_STATE_ON_LOCKED && 1431fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1432fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || !mNfceeRouteEnabled) { 1433fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE ON"); 1434fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = true; 1435e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doSelectSecureElement(); 1436fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1437fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 1438fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfceeRouteEnabled) { 1439fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1440fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1441e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doDeselectSecureElement(); 1442e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1443fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1444fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1445fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // configure NFC-C polling 1446fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (mScreenState >= POLLING_MODE) { 1447fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || !mNfcPollingEnabled) { 1448fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C ON"); 1449fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = true; 1450fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.enableDiscovery(); 1451fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1452221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } else { 1453fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (force || mNfcPollingEnabled) { 1454fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-C OFF"); 1455fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfcPollingEnabled = false; 1456fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.disableDiscovery(); 1457fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1458221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 145965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 146065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 146165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 14622436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 146331949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 14649a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1465a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1466a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 146731949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 146831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 146931949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 147031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 147131949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 147231949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 147331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 147431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 147531949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 147631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 147731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 147831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 147931949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 148031949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 148131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 148231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 148331949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 148431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 148531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 148631949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 148731949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 148831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 148931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1490bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1491bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1492bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1493bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1494bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 149531949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 149631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 149731949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 149831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 149931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 15002f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 150131949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 15020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1503f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1504f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 150531949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 150631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 150731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1508f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1509b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1510b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 151131949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 151231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 151331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 151431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1515f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1516f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1517d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 15184a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1519c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 15204a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1521d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1522d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1523d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 15243b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1525e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 15263b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1527e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1528e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 1529e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen /** For use by code in this process */ 15304a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1531c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 15324a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1533d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1534d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 153557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1536b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 153757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 153857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1539b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1540b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1541b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1542b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1543b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1544b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1545b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 15463fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1547b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1548b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 154931949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 155231949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 155731949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 155831949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 155931949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 156031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 156131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 1562ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag); 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 1564d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 156577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 1566d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 156731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 156831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 156931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 157057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 157131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 157231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 157331949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 1574d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_START); 1575391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 1576c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 1577391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 157831949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 1579ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 158031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 158131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 158231949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 1583ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 158431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 158531949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1586d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 158731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 158831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 158931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 159031949217328bf2357ff044f0d18677fe588c790cNick Pelly 159131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 159231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 159331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 159431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 159531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 159631949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 159731949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 159831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 159914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 160031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 160131949217328bf2357ff044f0d18677fe588c790cNick Pelly 160231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 160331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 160431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 160531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 160631949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 160731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 160814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 160931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 161031949217328bf2357ff044f0d18677fe588c790cNick Pelly 161131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 161231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 161331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 161431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 161531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 161631949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 161731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 161831949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 161931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 162031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 162114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 162231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 162331949217328bf2357ff044f0d18677fe588c790cNick Pelly 162431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 162531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 162631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 162731949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 162831949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 162931949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 163031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 163131949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 163231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 163331949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 163431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 163531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 163614a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 163731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 1638c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 163931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 164031949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 164131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 164231949217328bf2357ff044f0d18677fe588c790cNick Pelly 164331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 164431949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 164531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 164631949217328bf2357ff044f0d18677fe588c790cNick Pelly 164731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 164831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 164931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 165031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 165131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 165231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 165331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 165431949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 165531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 165631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 165731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 165831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 165931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 166031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 166131949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 166231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 166331949217328bf2357ff044f0d18677fe588c790cNick Pelly 166477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 166531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 166631949217328bf2357ff044f0d18677fe588c790cNick Pelly 166731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 166831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 166931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 167031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 167131949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 167231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 167331949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 167431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 167531949217328bf2357ff044f0d18677fe588c790cNick Pelly 167631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 167731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 167831949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 167931949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 168014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 168131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 168231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 168331949217328bf2357ff044f0d18677fe588c790cNick Pelly 168431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 168531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 168631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 168731949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 168814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 168931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 169031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 169131949217328bf2357ff044f0d18677fe588c790cNick Pelly 169231949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 169331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 169431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1696b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1697d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 169814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 169914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1700c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Resume app switches so the receivers can start activites without delay 1701c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfcDispatcher.resumeAppSwitches(); 1702c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 1703e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized(this) { 1704e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen for (PackageInfo pkg : mInstalledPackages) { 1705e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (pkg != null && pkg.applicationInfo != null) { 1706e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 1707e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen intent.setPackage(pkg.packageName); 1708e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mContext.sendBroadcast(intent); 1709e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 1710c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1711c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1712c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 171314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 171414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 1715d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1716d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1717d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1718d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1719d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1720d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1721d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1722d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1723d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1724d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1725d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 172631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 172731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 172831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1729d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 173077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1731d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1732d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1733d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1734d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1735d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1736d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1737d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1738d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1739d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1740d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1741d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1742d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1743d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1744d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1745d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1746d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1747d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1748d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1749d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1750d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1751d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1752d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1753d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1754d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 175531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 175631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 175731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1758d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 175977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1760d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1761d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1762d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1763d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1764d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1765d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1766d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1767d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1768d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1769d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1770ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly private void dispatchTagEndpoint(TagEndpoint tagEndpoint) { 1771f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1772f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1773f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 1774ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly if (!mNfcDispatcher.dispatchTag(tag)) { 1775f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1776d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 1777d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1778d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 17793fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 17803fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1781b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1782b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1783b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 178449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1785fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 1786fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1787fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 1788fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 1789fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 1790fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 1791fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1792fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 1793161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1794fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 1795fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1796fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean needWakelock = mScreenState == SCREEN_STATE_OFF; 1797fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (needWakelock) { 1798fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock.acquire(); 1799fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1800fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(false); 1801fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (needWakelock) { 1802fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mWakeLock.release(); 1803161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1804fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 18057c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 18067c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 18077c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 18087c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 18090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 18100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 18110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 181231949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 181331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (action.equals( 1814f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 1815fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Perform applyRouting() in AsyncTask to serialize blocking calls 1816fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly new ApplyRoutingTask().execute(); 1817fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_SCREEN_ON) 1818fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly || action.equals(Intent.ACTION_SCREEN_OFF) 1819fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly || action.equals(Intent.ACTION_USER_PRESENT)) { 1820fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Perform applyRouting() in AsyncTask to serialize blocking calls 1821fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int screenState = SCREEN_STATE_OFF; 1822fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1823fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = SCREEN_STATE_OFF; 1824fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1825fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = mKeyguard.isKeyguardLocked() ? 1826fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED; 1827fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1828fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly screenState = SCREEN_STATE_ON_UNLOCKED; 1829fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1830fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 183131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 183231949217328bf2357ff044f0d18677fe588c790cNick Pelly EnableDisableTask eeWipeTask = new EnableDisableTask(); 183331949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.execute(TASK_EE_WIPE); 183431949217328bf2357ff044f0d18677fe588c790cNick Pelly try { 183531949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.get(); // blocks until EE wipe is complete 183631949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (ExecutionException e) { 183731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 183831949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (InterruptedException e) { 183931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 184031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1841e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 1842e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 1843e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 1844e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 1845e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 1846e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 1847e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 1848e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 1849e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mNfceeAccessControl.invalidateCache(); 1850e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 1851e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 1852e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (dataRemoved) { 1853e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen Uri data = intent.getData(); 1854e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (data == null) return; 1855e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen String packageName = data.getSchemeSpecificPart(); 18567a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 1857e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (NfcService.this) { 1858e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mSePackages.contains(packageName)) { 1859e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen new EnableDisableTask().execute(TASK_EE_WIPE); 1860e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mSePackages.remove(packageName); 1861e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 18627a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 1863bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1864bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 186531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 186631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 186731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 186831949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 186931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 187031949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 187131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 187231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 187331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 187431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 18751668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 18761668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 187731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 187831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 187931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 188031949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 188131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1882f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1884f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 188531949217328bf2357ff044f0d18677fe588c790cNick Pelly 188631949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 188731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 188831949217328bf2357ff044f0d18677fe588c790cNick Pelly return Settings.System.getInt(mContext.getContentResolver(), 188931949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_ON, 0) == 1; 189031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 189131949217328bf2357ff044f0d18677fe588c790cNick Pelly 1892fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** for debugging only - no i18n */ 189331949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 189431949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 189531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 189631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 189731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 189831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 189931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 190031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 190131949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 190231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 190331949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 190431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 190531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 190631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 190731949217328bf2357ff044f0d18677fe588c790cNick Pelly 1908fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** For debugging only - no i18n */ 1909fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static String screenStateToString(int screenState) { 1910fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly switch (screenState) { 1911fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_OFF: 1912fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "OFF"; 1913fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_LOCKED: 1914fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_LOCKED"; 1915fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_UNLOCKED: 1916fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_UNLOCKED"; 1917fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly default: 1918fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "UNKNOWN"; 1919fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1920fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1921fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 192231949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 192350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 192450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 192550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 192650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 192750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 192850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 192950effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 193050effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 193131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 193231949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 19330b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 1934fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mScreenState=" + screenStateToString(mScreenState)); 1935fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled); 1936fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled); 193731949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 193831949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 193992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly pw.println("mOpenEe=" + mOpenEe); 194077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 1941c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.dump(fd, pw, args); 1942391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 194356f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 1944c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 194531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 194631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 194774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 1948