NfcService.java revision 3e38dca2bc7c7629d7159663d597a1e886d85527
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; 264bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.NativeNfcManager; 274bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.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; 407d8987f233985a5ff29226890e11012275d325f5Martijn Coenenimport android.content.res.Resources.NotFoundException; 41d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 42d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 462094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4849d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 549d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 55aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 577c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 5850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 59b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 60b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 6149d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 62b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 63533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 644467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 65f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 6613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 673e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenenimport android.os.SystemClock; 68525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.os.UserHandle; 69d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 70f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 71f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 7231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 7357d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 7431949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 7531949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 763ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 7784e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 78c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamiltonimport java.util.List; 7931949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 803ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 81525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectpublic class NfcService implements DeviceHostListener { 82bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 83bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 84c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 8576a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 86fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 87d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 88fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 89c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** Regular NFC permission */ 90bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 91bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 92c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 93c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** NFC ADMIN permission - only for system apps */ 94bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 95bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 96bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 9777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 98f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 99416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 100416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 101416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 102416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 103416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 104416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1051668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 106a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 107b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 108b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 109b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 110b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 111b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 112b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 113c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 114c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1152c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1162c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1172c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 118525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_ACTIVATED = 13; 119525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_DEACTIVATED = 14; 12057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen static final int MSG_LLCP_LINK_FIRST_PACKET = 15; 121b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 12231949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 12331949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 12431949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 12531949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 12631949217328bf2357ff044f0d18677fe588c790cNick Pelly 127fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Screen state, used by mScreenState 128fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_UNKNOWN = 0; 129fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_OFF = 1; 130fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_LOCKED = 2; 131fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_UNLOCKED = 3; 132fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 13349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 13449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 13549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 13649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1377efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 138c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // Return values from NfcEe.open() - these are 1:1 mapped 139c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // to the thrown EE_EXCEPTION_ exceptions in nfc-extras. 140c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_IO = -1; 141c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_ALREADY_OPEN = -2; 142c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_INIT = -3; 143c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_LISTEN_MODE = -4; 144c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_EXT_FIELD = -5; 145c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_NFC_DISABLED = -6; 146c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 147fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** minimum screen state that enables NFC polling (discovery) */ 148fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; 149fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 150525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for NFC controller to initialize before watchdog 151525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off. This time is chosen large, because firmware download 152525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // may be a part of initialization. 153525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int INIT_WATCHDOG_MS = 90000; 154525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 155525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for routing to be applied before watchdog 156525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off 157525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int ROUTING_WATCHDOG_MS = 10000; 158525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1593e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Amount of time to wait before closing the NFCEE connection 1603e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // in a disable/shutdown scenario. 1613e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_OPERATIONS_MS = 5000; 1623e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Polling interval for waiting on NFCEE operations 1633e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_POLL_MS = 100; 1643e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 165d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 166d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 167d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 168d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 169d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 17049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 17149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 17249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 17349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 17449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 17549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 17649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 17749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1782c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1792c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1802c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1812c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1822c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1832c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 1842c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 1852c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1862c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 1872c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 1882c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 1892c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 1902c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 191525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_ACTIVATED = 192525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED"; 193525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_DEACTIVATED = 194525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED"; 19549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 19649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 19749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 1980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 19949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 20049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 2010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 202d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 203d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 204d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 2052f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 206fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 207525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // mSePackages holds packages that accessed the SE, but only for the owner user, 208525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // as SE access is not granted for non-owner users. 209fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly HashSet<String> mSePackages = new HashSet<String>(); 210fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 2117d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 212fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 213fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing 214fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling 215e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 21631949217328bf2357ff044f0d18677fe588c790cNick Pelly 21731949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 21831949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 21931949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 22031949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 2212f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 2222f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 22305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 2244a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 2250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 227525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mRoutingWakeLock; 228525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mEeWakeLock; 229525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 230d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 231d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 232d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 233d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 23477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2354a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2364a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2374a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 23831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 23931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 240c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfceeAccessControl mNfceeAccessControl; 2412ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 24276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 243fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 244275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 2457d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private HandoverManager mHandoverManager; 2467d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private ContentResolver mContentResolver; 247d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 248d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 249d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 25093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 251c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 25293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 25393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 254c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void enforceNfceeAdminPerm(String pkg) { 255c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (pkg == null) { 256c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException("caller must pass a package name"); 257c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 258c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 259c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) { 260c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH + 261c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton " denies NFCEE access to " + pkg); 262c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 263525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { 264525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project throw new SecurityException("only the owner is allowed to call SE APIs"); 265525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 26693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 26793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 268d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 269d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 270d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 271f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 273f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 274f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 275f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 277f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 278f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 279f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 280d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 281f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 282f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 283f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 284f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 285f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 286f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 287f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 288d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 289f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 290f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_CARD_EMULATION, aid); 291f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 292f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 293f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 294f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 295f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 296f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 297f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 298f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 299f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 300f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 301f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 302f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 303f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 304d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 305f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 306f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 307f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 308f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 30957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen /** 31057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen * Notifies P2P Device detected, first packet received over LLCP link 31157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen */ 31257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 31357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 31457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 31557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 31657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 317d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 318f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 319f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 320f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 321f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 322d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 323f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 324f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 325f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 326f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 327f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 328525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenActivated() { 329525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null); 330525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 331525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 332525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 333525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenDeactivated() { 334525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null); 335525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 336525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 337525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 338525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 339442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 340442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 341442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 342442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 343442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 344442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 345442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 346442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 347442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 348442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 349442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 350442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 351442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 352442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 353525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public NfcService(Application nfcApplication) { 3544a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 3554a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 356ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 3574a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 3582f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 3592f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 360d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 361d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 362525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext = nfcApplication; 3637d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mContentResolver = mContext.getContentResolver(); 364525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost = new NativeNfcManager(mContext, this); 36574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 3667d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager = new HandoverManager(mContext); 3677d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean isNfcProvisioningEnabled = false; 3687d8987f233985a5ff29226890e11012275d325f5Martijn Coenen try { 3697d8987f233985a5ff29226890e11012275d325f5Martijn Coenen isNfcProvisioningEnabled = mContext.getResources().getBoolean( 3707d8987f233985a5ff29226890e11012275d325f5Martijn Coenen R.bool.enable_nfc_provisioning); 3717d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } catch (NotFoundException e) { 3727d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 3737d8987f233985a5ff29226890e11012275d325f5Martijn Coenen 3747d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (isNfcProvisioningEnabled) { 3757d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 3767d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 3777d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else { 3787d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = false; 3797d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 380525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 3817d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(!mInProvisionMode); 3827d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode); 3837d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager, 384525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 38524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 38637058bf7b59def2f9a565ae5b16aae54e80e9e95Sunil Jogi mSecureElement = new NativeNfcSecureElement(mContext); 387eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 3880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 389525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mNfceeAccessControl = new NfceeAccessControl(mContext); 390c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 391525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 3920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 39431949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3950b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 397525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 398525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 399525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock = mPowerManager.newWakeLock( 400525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 401525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock = mPowerManager.newWakeLock( 402525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock"); 403275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 404525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 405fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = checkScreenState(); 406533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 407d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 409525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents only for owner 410525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 411525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 412525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 413525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 414525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 415525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiver(mOwnerReceiver, ownerFilter); 416525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 417525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter = new IntentFilter(); 418525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 419525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 420525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ownerFilter.addDataScheme("package"); 421525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 422525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiver(mOwnerReceiver, ownerFilter); 423525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 424525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents for all users 425eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 42665945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 42765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 428275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 4293859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen filter.addAction(Intent.ACTION_USER_SWITCHED); 43031949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 431525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 4320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 433e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 434e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 43531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 43631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly 438d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 439d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 440d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 441d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 442525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 443525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 444525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 445d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 446d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 447d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 448d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 449d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 450d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 451d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 452d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 453d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 454d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 455d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 456d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 457d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 4597d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String airplaneModeRadios = Settings.System.getString(mContentResolver, 4607d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_RADIOS); 4617d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String toggleableRadios = Settings.System.getString(mContentResolver, 4627d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 46331949217328bf2357ff044f0d18677fe588c790cNick Pelly 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 4657d8987f233985a5ff29226890e11012275d325f5Martijn Coenen airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 46631949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 4677d8987f233985a5ff29226890e11012275d325f5Martijn Coenen toggleableRadios.contains(Settings.Global.RADIO_NFC); 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly 474e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen void updatePackageCache() { 475525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PackageManager pm = mContext.getPackageManager(); 476525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER); 477e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (this) { 478e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mInstalledPackages = packages; 479e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 480e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 481e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 482fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int checkScreenState() { 483fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (!mPowerManager.isScreenOn()) { 484fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_OFF; 485fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (mKeyguard.isKeyguardLocked()) { 486fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_LOCKED; 487fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 488fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_UNLOCKED; 489fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 490fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 491fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 492525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int doOpenSecureElementConnection() { 493525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 494525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 495525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doOpenSecureElementConnection(); 496525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 497525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 498525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 499525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 500525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 501525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceive(int handle, byte[] cmd) { 502525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 503525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 504525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceiveNoLock(handle, cmd); 505525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 506525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 507525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 508525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 509525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 510525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceiveNoLock(int handle, byte[] cmd) { 511525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doTransceive(handle, cmd); 512525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 513525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 514525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project void doDisconnect(int handle) { 515525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 516525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 517525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mSecureElement.doDisconnect(handle); 518525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 519525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 520525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 521525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 522525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 52331949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 52531949217328bf2357ff044f0d18677fe588c790cNick Pelly * 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 52731949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 52831949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 52931949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 53031949217328bf2357ff044f0d18677fe588c790cNick Pelly * 53131949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 53231949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 53331949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 53531949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 53631949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 53731949217328bf2357ff044f0d18677fe588c790cNick Pelly * 53831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 53931949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 54131949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly * 54431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 55131949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 55331949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 55431949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 55531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly 5644467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 5654467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 5664467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 5674467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 5684467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 5694467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 5704467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 5714467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 5724467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 57331949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 57431949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 57631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 57831949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 57931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 58031949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 5810fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 5821668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 58331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 5841668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 5850fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 58631949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 5870fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 5880fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 5890fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 59031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 59231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 59331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 59431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 59531949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 59631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 59731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 59831949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 59931949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 60031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 60131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 602d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 603d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 604d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 60531949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 60631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60731949217328bf2357ff044f0d18677fe588c790cNick Pelly 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 61031949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 61231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 61731949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 61831949217328bf2357ff044f0d18677fe588c790cNick Pelly 619525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 620525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.start(); 621525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 622525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 623525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 624525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (!mDeviceHost.initialize()) { 625525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Error enabling NFC"); 626525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project updateState(NfcAdapter.STATE_OFF); 627525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return false; 628525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 629525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 630525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 631525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 632525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 633525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.cancel(); 63431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 63531949217328bf2357ff044f0d18677fe588c790cNick Pelly 63631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 63731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 63831949217328bf2357ff044f0d18677fe588c790cNick Pelly 6390b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 64031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 64131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 64231949217328bf2357ff044f0d18677fe588c790cNick Pelly 643d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 644d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 64531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 6460c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 647fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 64831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 64931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 65031949217328bf2357ff044f0d18677fe588c790cNick Pelly 65131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 65331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 65431949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 65631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 65731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 65831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 65931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 66031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 66131949217328bf2357ff044f0d18677fe588c790cNick Pelly 66231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 66331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 66431949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 66531949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 666525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 66731949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 66831949217328bf2357ff044f0d18677fe588c790cNick Pelly 66977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 67031949217328bf2357ff044f0d18677fe588c790cNick Pelly 6713e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen /* The NFC-EE may still be opened by another process, 6723e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * and a transceive() could still be in progress on 6733e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * another Binder thread. 6743e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * Give it a while to finish existing operations 6753e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * before we close it. 6763e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen */ 6773e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Long startTime = SystemClock.elapsedRealtime(); 6783e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen do { 6793e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen synchronized (NfcService.this) { 6803e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen if (mOpenEe == null) 6813e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen break; 6823e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 6833e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen try { 6843e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Thread.sleep(WAIT_FOR_NFCEE_POLL_MS); 6853e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } catch (InterruptedException e) { 6863e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Ignore 6873e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 6883e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } while (SystemClock.elapsedRealtime() - startTime < WAIT_FOR_NFCEE_OPERATIONS_MS); 6893e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 6904ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen synchronized (NfcService.this) { 6914ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (mOpenEe != null) { 6924ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen try { 6934ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen _nfcEeClose(-1, mOpenEe.binder); 6944ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } catch (IOException e) { } 6954ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 6964ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 6974ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen 69831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 69931949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 70031949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 70131949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 70231949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 70331949217328bf2357ff044f0d18677fe588c790cNick Pelly 7040b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 70531949217328bf2357ff044f0d18677fe588c790cNick Pelly 70631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 70731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 70831949217328bf2357ff044f0d18677fe588c790cNick Pelly 70931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 71031949217328bf2357ff044f0d18677fe588c790cNick Pelly 71131949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 71231949217328bf2357ff044f0d18677fe588c790cNick Pelly 713d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 714d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 71531949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 71631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 71731949217328bf2357ff044f0d18677fe588c790cNick Pelly 71831949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 71931949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 720525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[][]apdus = mDeviceHost.getWipeApdus(); 721525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 722525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (apdus == null) { 723525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.d(TAG, "No wipe APDUs found"); 724525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 725525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 72631949217328bf2357ff044f0d18677fe588c790cNick Pelly 72731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 728525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Hold a wake-lock over the entire wipe procedure 729525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 730525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 731525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable && !enableInternal()) { 732ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 73331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 734f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 735525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 736525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // NFC enabled 737525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = 0; 738525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 739525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "Executing SE wipe"); 740525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project handle = doOpenSecureElementConnection(); 741525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (handle == 0) { 742525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Could not open the secure element"); 743525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 744525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 745525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // TODO: remove this hack 746525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 747525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Thread.sleep(1000); 748525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 749525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Ignore 750525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 75131949217328bf2357ff044f0d18677fe588c790cNick Pelly 752525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 753525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 754525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (byte[] cmd : apdus) { 755525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] resp = doTransceiveNoLock(handle, cmd); 756525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (resp == null) { 757525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 758525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 759525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 760525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 761525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 762525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.resetTimeouts(); 763525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 764525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 765525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (handle != 0) { 766525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(handle); 767525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 768525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 769525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 770525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable) { 771525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project disableInternal(); 772525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 773ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 774525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 775525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 77631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 777525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "SE wipe done"); 77831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 77931949217328bf2357ff044f0d18677fe588c790cNick Pelly 78031949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 7812a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 78231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 78331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 78431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 78531949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 78631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 78731949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 78831949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 789525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 79031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79331949217328bf2357ff044f0d18677fe588c790cNick Pelly 79431949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 79531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 79631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 79731949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 79831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 8000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 801d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 802d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 803d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 804d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 805d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 806d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 807d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 808d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 809d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 810d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 811d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 812d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 813d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 814d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 815d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 816d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 817d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 818d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 819d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 820d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 8210e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 8224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 823fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 8240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 82593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 8260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 82731949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 8281668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 8291668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 8301668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 8311668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 8321668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 8331668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 8341668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 8351668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 8361668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 837f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 83831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 83931949217328bf2357ff044f0d18677fe588c790cNick Pelly 84031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 841f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 842f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 843fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 844290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 84593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 8460e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 847290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 848290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 849290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 850290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 85131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 85231949217328bf2357ff044f0d18677fe588c790cNick Pelly 85331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 854f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 855f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 856fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 8570b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 85831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 8599993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 86031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 861d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 862d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 863d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 8640b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 865d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 866d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 8670b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 86831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 86931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 8700b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 8710b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 87231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 8730b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 87431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 87577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 876d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 877d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 878d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 879d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 880d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 881d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 8820b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 883d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 884d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 8850b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 88631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 88731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 8880b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 8890b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 89031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 8910b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 89231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 89377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 894d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 895d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 896d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 897d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 898d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 899d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9000b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 90124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 90205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 903a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 9040b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 9050b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 9060b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 9070b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 908ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 909a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 910a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 911a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 912a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 913a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 914a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 915a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 916a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 917a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 918a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 919a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 920a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 921a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 922a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 92324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 92424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 92524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 92624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 92724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 92849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 9290b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 9302094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 9312094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 9322094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 933c96f982f8c0fa061701143a27395acf3b24dfb54Nick Pelly public void setNdefPushCallback(INdefPushCallback callback) { 934ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 9353859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 936ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 937ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 938ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 9390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 9400e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 9410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 9420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 943fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 944c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) { 945c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 94649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 9470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 9480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 949fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 95031949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 95131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 95231949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 95331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 95431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 95531949217328bf2357ff044f0d18677fe588c790cNick Pelly 95631949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 95731949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 95831949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 9590e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 960391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 961391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 962ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 963391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly enforceAdminPerm(mContext); 964ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 965391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 9660c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 9670c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 9680c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 9690c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen enforceAdminPerm(mContext); 9700c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 9710c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 9720c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 9730c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.disableDiscovery(); 9740c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.enableDiscovery(); 9750c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 976c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 9770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 9784a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 979fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 981d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 982bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 983f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 98531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 989f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 990f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 992b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 993b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 99421545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 995b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 998fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1002fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1003ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 1004d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1005bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1006f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1007f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 100831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1013f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1014b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1015b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1017ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 1018cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 1019cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1020cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 1021cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 1022ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 1023ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 1024ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 1025ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 1026ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 1027ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 1028ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1029ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1032fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1033aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 1034aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1035aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1036f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1037aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1038aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 103931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1040aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 1041aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1042aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1043aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 1044f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1045aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 1046aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 1047aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 1048aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 1049aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1050aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1051aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1052aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1053aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1054aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1055aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 1056b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 1057d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1058bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1059f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 106031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1062f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1064f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1065f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1066f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1067b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 1068f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1069f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1070f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1071f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1072fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1073b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 1074f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1075b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1076b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 107731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1078b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1079b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1080b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1081b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 1082f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1083b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1084b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1085b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1086b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1087ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 1088b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1089b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1090fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1091f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 1092182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1093182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 1094f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1095f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1096f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 109731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10982c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1099f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1101f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1102f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 11033ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 11042c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 11052c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 110770bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 1108f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1110fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11119d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 111297c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 1113d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1114bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1115f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 1117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 111931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1120f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1121f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1122f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1123f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1124f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1125f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1126bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 1127bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1128bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1129bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 11309d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 11319d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 1132bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 1133bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 1134bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 1135bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 1136bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 1137bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 1138bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 1139bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1140bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1145fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1147d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1148bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1149f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 115231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1157f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1159f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1160f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1162f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1165f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1171f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1173f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1174fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11753fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1176d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1177bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1178f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1179f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1180f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 118131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1186f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1187f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1191791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1192791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1193f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1195f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1201fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12023fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 12033fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1206fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 120803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 120903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1210f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 121103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 121203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 121331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 121403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 121503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 121603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 121703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1218f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 121903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 122003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 122103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 122203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1223f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 122403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1225f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 122603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 122703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 12300aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 12310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 12320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 12330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1234f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 12350aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12360aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 123731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 12380aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 12390aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12400aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12410aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 12430aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 12440aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12450aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12460aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12470aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 12480aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 12500aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12510aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12520aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12530aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12541b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 12553fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 12563fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 12573fb14d0868594c78a777e805545209636814e223Martijn Coenen 1258f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 12593fb14d0868594c78a777e805545209636814e223Martijn Coenen 12603fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 126131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 12623fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 12633fb14d0868594c78a777e805545209636814e223Martijn Coenen } 12643fb14d0868594c78a777e805545209636814e223Martijn Coenen 12653fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 12673fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 12683fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 12693fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 12703fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 12713fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 12723fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 12733fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 12743fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 12753fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 12763fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 12773fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1278391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 12793fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 12803fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 12814a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 12823fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 12833fb14d0868594c78a777e805545209636814e223Martijn Coenen } 12843fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 12853fb14d0868594c78a777e805545209636814e223Martijn Coenen } 12863fb14d0868594c78a777e805545209636814e223Martijn Coenen 12871b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1288fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 12891b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1290f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1291fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1292fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1293fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1294fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1295fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1296dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1297dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1298dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1299358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1300358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1301358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1302358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1303358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1304358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1305358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1306dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1307dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1308dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1309f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 13101b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1311bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1312bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1313bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1314bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1315bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1316bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1317bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1318bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1319bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1320bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1321ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1322ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1323ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1324ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1325ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1326c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 132892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly void _nfcEeClose(int callingPid, IBinder binder) throws IOException { 1329dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1330dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1331dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1332dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 13330571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly synchronized (NfcService.this) { 13344ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1335dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1336dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1337dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1338dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1339dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 134092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (callingPid != -1 && callingPid != mOpenEe.pid) { 1341dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1342dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 134392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (mOpenEe.binder != binder) { 134492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly throw new SecurityException("Wrong binder handle"); 134592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 1346dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 134792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly binder.unlinkToDeath(mOpenEe, 0); 1348f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1349525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(mOpenEe.handle); 1350dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1351dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1352fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1353dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1354dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1355dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 13564a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 135749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 135849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 135949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 136049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 136149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1362c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1363c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private Bundle writeEeException(int exceptionType, String message) { 136449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 1365c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putInt("e", exceptionType); 1366c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putString("m", message); 136749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 136849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 13690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1370bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1371c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle open(String pkg, IBinder b) throws RemoteException { 1372c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1373bd555ee64250126b60b24814120a2049943920caNick Pelly 137449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 1375c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen int handle = _open(b); 1376c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1377c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(handle, "NFCEE open exception."); 1378c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen } else { 137949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 13800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 138149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 138249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 13830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1384c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen /** 1385c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * Opens a connection to the secure element. 1386c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * 1387c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * @return A handle with a value >= 0 in case of success, or a 1388c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * negative value in case of failure. 1389c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen */ 1390c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private int _open(IBinder b) { 139149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 139231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1393c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_NFC_DISABLED; 139449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 139549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 1396c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_ALREADY_OPEN; 139749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 13980bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1399525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = doOpenSecureElementConnection(); 1400c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1401c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 140249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1403525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000); 1404ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 140592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle, b); 140649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 140749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 140849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 140949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 141049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 141184e1e0adc2516afd35ebab029a52e764e0490559Jason parks 141284e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 141384e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 1414525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) { 141584e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 141684e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 1417c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1418c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 141949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 14200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 14210bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1422bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 142392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public Bundle close(String pkg, IBinder binder) throws RemoteException { 1424c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1425c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 142649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 142749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 142892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(getCallingPid(), binder); 142949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 143049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1431c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 14320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 143349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 143449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 14350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1436bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1437c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle transceive(String pkg, byte[] in) throws RemoteException { 1438c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1439bd555ee64250126b60b24814120a2049943920caNick Pelly 144049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 144149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 144249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 144349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 144449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 144549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 144649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1447c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 14480bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 144949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 145049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 14510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1452c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private byte[] _transceive(byte[] data) throws IOException { 145349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 145431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 145549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 145649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 14570571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly if (mOpenEe == null) { 145849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 145949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 146049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 146149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 146249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 14630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 14640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1465525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceive(mOpenEe.handle, data); 14660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 14670bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1468bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1469c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public int getCardEmulationRoute(String pkg) throws RemoteException { 1470c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 147149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 14720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 14730bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1474bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1475c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void setCardEmulationRoute(String pkg, int route) throws RemoteException { 1476c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 147749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 1478525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask(); 1479525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.execute(); 1480525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 1481525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Block until route is set 1482525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.get(); 1483525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 1484525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1485525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 1486525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1487525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 14880bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1489bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1490bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1491c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void authenticate(String pkg, byte[] token) throws RemoteException { 1492c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1493bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1494525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1495525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 1496525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public String getDriverName(String pkg) throws RemoteException { 1497525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NfcService.this.enforceNfceeAdminPerm(pkg); 1498525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mDeviceHost.getName(); 1499525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1500c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 15010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 150249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 150349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 150449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 150592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // binder handle used for DeathReceipient. Must keep 150692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // a reference to this, otherwise it can get GC'd and 150792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // the binder stub code might create a different BinderProxy 150892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // for the same remote IBinder, causing mismatched 150992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // link()/unlink() 151092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public IBinder binder; 151149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 151292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public OpenSecureElement(int pid, int handle, IBinder binder) { 151349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 151449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 151592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly this.binder = binder; 151649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1517bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 151849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 151949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 152092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly Log.i(TAG, "Tracked app " + pid + " died"); 152149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 15220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 152392250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(-1, binder); 1524dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 15250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 15260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 152792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly @Override 152892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public String toString() { 152992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=") 153092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly .append(pid).append(" handle=").append(handle).append("]").toString(); 153192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 15320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 15330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 15349a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 15359a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 15369a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 15379a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 15389a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 15399a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 154031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 154131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 154231949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1543e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1544aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1545aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 1547a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project final Object mCancelWaiter = new Object(); 1548525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project final int mTimeout; 1549a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project boolean mCanceled = false; 1550525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1551525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public WatchDogThread(String threadName, int timeout) { 1552525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project super(threadName); 1553525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mTimeout = timeout; 1554525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1555525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 15562edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 15572edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 1558a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project try { 1559a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1560a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.wait(mTimeout); 1561a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project if (mCanceled) { 1562a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project return; 1563a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 15642edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1565a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } catch (InterruptedException e) { 1566a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project // Should not happen; fall-through to abort. 1567a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.w(TAG, "Watchdog thread interruped."); 1568a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project interrupt(); 15692edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1570a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.e(TAG, "Watchdog triggered, aborting."); 1571a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mDeviceHost.doAbort(); 15722edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1573a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project 15742edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 1575a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1576a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCanceled = true; 1577a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.notify(); 1578a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 15792edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 15802edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 15812edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 1582fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1583fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1584fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1585fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1586e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 15879a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) { 1588fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // PN544 cannot be reconfigured while EE is open 1589e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1590e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1591525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 15927d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (mInProvisionMode) { 15937d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 15947d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 15957d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mInProvisionMode) { 15967d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Notify dispatcher it's fine to dispatch to any package now 15977d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // and allow handover transfers. 15987d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher.disableProvisioningMode(); 15997d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(true); 16007d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 16017d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1602f439271150e4548f116919e0254d57655421581cMartijn Coenen try { 1603f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.start(); 1604f439271150e4548f116919e0254d57655421581cMartijn Coenen 1605525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) { 1606f439271150e4548f116919e0254d57655421581cMartijn Coenen /* TODO undo this after the LLCP stack is fixed. 1607f439271150e4548f116919e0254d57655421581cMartijn Coenen * Use a different sequence when turning the screen off to 1608f439271150e4548f116919e0254d57655421581cMartijn Coenen * workaround race conditions in pn544 libnfc. The race occurs 1609f439271150e4548f116919e0254d57655421581cMartijn Coenen * when we change routing while there is a P2P target connect. 1610f439271150e4548f116919e0254d57655421581cMartijn Coenen * The async LLCP callback will crash since the routing code 1611f439271150e4548f116919e0254d57655421581cMartijn Coenen * is overwriting globals it relies on. 1612f439271150e4548f116919e0254d57655421581cMartijn Coenen */ 1613f439271150e4548f116919e0254d57655421581cMartijn Coenen if (POLLING_MODE > SCREEN_STATE_OFF) { 1614f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1615f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF, disconnect"); 1616f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1617f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1618f439271150e4548f116919e0254d57655421581cMartijn Coenen maybeDisconnectTarget(); 1619f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1620f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1621f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1622f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1623f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE OFF"); 1624f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = false; 1625f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doDeselectSecureElement(); 1626f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1627fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1628f439271150e4548f116919e0254d57655421581cMartijn Coenen return; 1629fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1630f439271150e4548f116919e0254d57655421581cMartijn Coenen 1631f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-EE routing 1632f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= SCREEN_STATE_ON_LOCKED && 1633f439271150e4548f116919e0254d57655421581cMartijn Coenen mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1634f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfceeRouteEnabled) { 1635f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE ON"); 1636f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = true; 1637f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doSelectSecureElement(); 1638f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1639f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1640f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1641fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1642fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1643fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.doDeselectSecureElement(); 1644fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1645fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1646fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1647f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-C polling 1648f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= POLLING_MODE) { 1649f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfcPollingEnabled) { 1650f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C ON"); 1651f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = true; 1652f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.enableDiscovery(); 1653f439271150e4548f116919e0254d57655421581cMartijn Coenen } 16547d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else if (mInProvisionMode && mScreenState >= SCREEN_STATE_ON_LOCKED) { 16557d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Special case for setup provisioning 16567d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mNfcPollingEnabled) { 16577d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Log.d(TAG, "NFC-C ON"); 16587d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcPollingEnabled = true; 16597d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mDeviceHost.enableDiscovery(); 16607d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1661f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1662f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1663f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF"); 1664f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1665f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1666f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1667fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1668f439271150e4548f116919e0254d57655421581cMartijn Coenen } finally { 1669f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.cancel(); 1670221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 167165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 167265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 167365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 16742436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 167531949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 16769a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1677a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1678a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 167931949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 168031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 168131949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 168231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 168331949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 168431949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 168531949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 168631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 168731949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 168831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 168931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 169031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 169131949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 169231949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 169331949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 169431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 169631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 169731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 169831949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 169931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 170031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 170131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1702bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1703bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1704bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1705bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1706bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 170731949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 170831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 170931949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 171031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 171131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 17122f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 171331949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 17140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1715f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1716f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 171731949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 171831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 171931949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1720f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1721b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1722b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 172331949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 172431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 172531949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 172631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1727f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1728f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1729d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 17304a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1731c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 17324a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1733d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1734d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1735d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 17363b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1737e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 17383b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1739e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1740e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 1741e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen /** For use by code in this process */ 17424a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1743c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 17444a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1745d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1746d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 174757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1748b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 174957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 175057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1751b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1752b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1753b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1754b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1755b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1756b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1757b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 17583fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1759b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1760b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 176131949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 176231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 176331949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 176431949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 176531949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 176631949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 176731949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 176831949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 176931949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 177031949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 177131949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 177231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 177331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 1774ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag); 177531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 1776d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 177777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 1778d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 178331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 178431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 178531949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 1786d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_START); 178789baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 178889baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // When these tags start containing NDEF, they will require 178989baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // the stack to deal with them in a different way, since 179089baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // they are activated only really shortly. 179189baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // For now, don't consider NDEF on these. 179289baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 179389baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen tag.startPresenceChecking(); 179489baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen dispatchTagEndpoint(tag); 179589baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen break; 179689baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen } 1797391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 1798c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 1799391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 180031949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 1801ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 180231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 180331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 180431949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 1805ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 180631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 180731949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1808d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 180931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 181031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 181131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 181231949217328bf2357ff044f0d18677fe588c790cNick Pelly 181331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 181431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 181531949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 181631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 181731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 181831949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 181931949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 182031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 182114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 182231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 182331949217328bf2357ff044f0d18677fe588c790cNick Pelly 182431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 182531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 182631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 182731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 182831949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 182931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 183014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 183131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 183231949217328bf2357ff044f0d18677fe588c790cNick Pelly 183331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 183431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 183531949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 183631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 183731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 183831949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 183931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 184031949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 184131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 184231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 184314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 184431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 184531949217328bf2357ff044f0d18677fe588c790cNick Pelly 184631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 184731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 184831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 184931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 185031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 185131949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 185231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 185331949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 185431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 185531949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 185631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 185731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 185814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 185931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 1860c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 186131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 186231949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 186331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 186431949217328bf2357ff044f0d18677fe588c790cNick Pelly 186531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 186631949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 186731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 186831949217328bf2357ff044f0d18677fe588c790cNick Pelly 186931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 187031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 187131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 187231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 187331949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 187431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 187531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 187631949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 187731949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 187831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 187931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 188031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 188131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 188231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 188331949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 188431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 188531949217328bf2357ff044f0d18677fe588c790cNick Pelly 188677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 188731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 188857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen case MSG_LLCP_LINK_FIRST_PACKET: 188957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mP2pLinkManager.onLlcpFirstPacketReceived(); 189057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen break; 189131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 189231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 189331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 189431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 189531949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 189631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 189731949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 189831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 189931949217328bf2357ff044f0d18677fe588c790cNick Pelly 190031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 190131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 190231949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 190331949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 190414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 190531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 190631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 190731949217328bf2357ff044f0d18677fe588c790cNick Pelly 190831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 190931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 191031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 191131949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 191214a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 191331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 191431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 191531949217328bf2357ff044f0d18677fe588c790cNick Pelly 1916525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_ACTIVATED: { 1917525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED"); 1918525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeActivated = new Intent(); 1919525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED); 1920525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeActivated); 1921525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 1922525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1923525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1924525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_DEACTIVATED: { 1925525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED"); 1926525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeDeactivated = new Intent(); 1927525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED); 1928525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeDeactivated); 1929525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 1930525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1931525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 193231949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 193331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 193431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 193531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1936b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1937d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 193814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 193914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1940c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Resume app switches so the receivers can start activites without delay 1941c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfcDispatcher.resumeAppSwitches(); 1942c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 1943e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized(this) { 1944e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen for (PackageInfo pkg : mInstalledPackages) { 1945e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (pkg != null && pkg.applicationInfo != null) { 1946e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 1947e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen intent.setPackage(pkg.packageName); 1948e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mContext.sendBroadcast(intent); 1949e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 1950c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1951c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 1952c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 195314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 195414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 1955d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1956d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1957d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1958d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1959d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1960d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1961d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1962d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1963d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1964d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1965d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 196631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 196731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 196831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1969d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 197077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1971d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1972d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1973d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1974d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1975d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1976d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1977d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1978d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1979d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1980d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1981d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1982d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1983d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1984d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1985d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1986d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1987d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1988d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1989d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1990d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1991d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1992d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1993d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1994d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 199531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 199631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 199731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1998d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 199977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 2000d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 2001d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2002d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2003d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 2004d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2005d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2006d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2007d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 2008d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2009d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2010ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly private void dispatchTagEndpoint(TagEndpoint tagEndpoint) { 2011f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 2012f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 2013f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 2014ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly if (!mNfcDispatcher.dispatchTag(tag)) { 2015f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 2016d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 2017d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2018d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 20193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 20203fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 2021b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 2022b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 2023b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 202449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 2025fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 2026fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 2027fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 2028fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 2029fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 2030fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 2031fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 2032fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 2033161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2034fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 2035fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 2036525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 2037525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2038525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRouting(false); 2039525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 2040525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 2041161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2042fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 20437c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 20447c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 20457c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 20467c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 2047525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() { 20480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 20490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 205031949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 2051525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 2052e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 2053e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 2054e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 2055e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 2056e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2057e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 2058e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 2059e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mNfceeAccessControl.invalidateCache(); 2060e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2061e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 2062e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (dataRemoved) { 2063e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen Uri data = intent.getData(); 2064e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (data == null) return; 2065e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen String packageName = data.getSchemeSpecificPart(); 20667a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 2067e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (NfcService.this) { 2068e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mSePackages.contains(packageName)) { 2069e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen new EnableDisableTask().execute(TASK_EE_WIPE); 2070e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mSePackages.remove(packageName); 2071e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 20727a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 2073bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2074bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2075525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 2076525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project EnableDisableTask eeWipeTask = new EnableDisableTask(); 2077525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.execute(TASK_EE_WIPE); 2078525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2079525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.get(); // blocks until EE wipe is complete 2080525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 2081525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2082525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 2083525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2084525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2085525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2086525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2087525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project }; 2088525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 2089525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2090525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 2091525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onReceive(Context context, Intent intent) { 2092525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project String action = intent.getAction(); 2093525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals( 2094525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2095525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2096525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(); 2097525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON) 2098525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_SCREEN_OFF) 2099525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_USER_PRESENT)) { 2100525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2101525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int screenState = SCREEN_STATE_OFF; 2102525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_SCREEN_OFF)) { 2103525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_OFF; 2104525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 2105525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = mKeyguard.isKeyguardLocked() ? 2106525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED; 2107525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 2108525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_ON_UNLOCKED; 2109525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2110525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 211131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 211231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 211331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 211431949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 211531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 211631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 211731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 211831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 211931949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 212031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 21211668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 21221668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 212331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 212431949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 212531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 212631949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 212731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 21283859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 21293859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.onUserSwitched(); 2130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2131f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 213331949217328bf2357ff044f0d18677fe588c790cNick Pelly 213431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 213531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 21367d8987f233985a5ff29226890e11012275d325f5Martijn Coenen return Settings.System.getInt(mContentResolver, 21377d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 213831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 213931949217328bf2357ff044f0d18677fe588c790cNick Pelly 2140fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** for debugging only - no i18n */ 214131949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 214231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 214331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 214431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 214531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 214631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 214731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 214831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 214931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 215031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 215131949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 215231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 215331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 215431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 215531949217328bf2357ff044f0d18677fe588c790cNick Pelly 2156fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** For debugging only - no i18n */ 2157fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static String screenStateToString(int screenState) { 2158fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly switch (screenState) { 2159fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_OFF: 2160fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "OFF"; 2161fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_LOCKED: 2162fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_LOCKED"; 2163fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_UNLOCKED: 2164fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_UNLOCKED"; 2165fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly default: 2166fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "UNKNOWN"; 2167fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2168fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2169fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 217031949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 217150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 217250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 217350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 217450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 217550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 217650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 217750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 217850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 217931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 218031949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 21810b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 2182fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mScreenState=" + screenStateToString(mScreenState)); 2183fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled); 2184fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled); 218531949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 218631949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 218792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly pw.println("mOpenEe=" + mOpenEe); 218877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 2189c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.dump(fd, pw, args); 2190391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 219156f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 2192c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 219331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 219431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 219574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 2196