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; 26d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport com.android.nfc.cardemulation.AidRoutingManager; 279f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenenimport com.android.nfc.cardemulation.HostEmulationManager; 2878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenenimport com.android.nfc.cardemulation.RegisteredAidCache; 294bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.NativeNfcManager; 304bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.NativeNfcSecureElement; 31c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 32efb7a3df560585994cebd40fcf5ffbc864f8c358Martijn Coenenimport android.app.ActivityManager; 332f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 34275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 3505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 37a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.content.ComponentName; 3831949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 4013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 4113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 43483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenenimport android.content.pm.PackageInfo; 4493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 457d8987f233985a5ff29226890e11012275d325f5Martijn Coenenimport android.content.res.Resources.NotFoundException; 46d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 47d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 5131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenenimport android.nfc.IAppCallback; 520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 5349d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 54a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.nfc.INfcCardEmulation; 55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 57f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 609d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 61a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.nfc.cardemulation.ApduServiceInfo; 62aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 6381c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 647c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 6550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 6696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenenimport android.os.Build; 67b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 68b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 6949d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 70b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 71533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 724467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 73f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 7413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 753e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenenimport android.os.SystemClock; 76525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.os.UserHandle; 77d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 78f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 7931949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 8057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 8131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 8231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 833ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 8484e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 85c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamiltonimport java.util.List; 86c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenenimport java.util.NoSuchElementException; 8731949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 883ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 89525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectpublic class NfcService implements DeviceHostListener { 90bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 91bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 92c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 9376a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 94fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 95d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 96fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 97c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** Regular NFC permission */ 98bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 99bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 100c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 101c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** NFC ADMIN permission - only for system apps */ 102bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 103bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 104bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 10577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 107416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 108416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 109416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 110416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 111416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 112416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1131668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 114a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen static final boolean SE_BROADCASTS_WITH_HCE = true; 115a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 116b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 120b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 121b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 122c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 123c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1242c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1252c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1262c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 127525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_ACTIVATED = 13; 128525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_DEACTIVATED = 14; 12957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen static final int MSG_LLCP_LINK_FIRST_PACKET = 15; 130d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_ROUTE_AID = 16; 131d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_UNROUTE_AID = 17; 132d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_COMMIT_ROUTING = 18; 133b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 13431949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 13531949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 13631949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 13731949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 13831949217328bf2357ff044f0d18677fe588c790cNick Pelly 139fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Screen state, used by mScreenState 140fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_UNKNOWN = 0; 141fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_OFF = 1; 142fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_LOCKED = 2; 143fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_UNLOCKED = 3; 144fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 14549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 14649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 14749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 14849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1497efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 150c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // Return values from NfcEe.open() - these are 1:1 mapped 151c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // to the thrown EE_EXCEPTION_ exceptions in nfc-extras. 152c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_IO = -1; 153c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_ALREADY_OPEN = -2; 154c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_INIT = -3; 155c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_LISTEN_MODE = -4; 156c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_EXT_FIELD = -5; 157c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_NFC_DISABLED = -6; 158c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 159fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** minimum screen state that enables NFC polling (discovery) */ 160fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; 161fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 162525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for NFC controller to initialize before watchdog 163525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off. This time is chosen large, because firmware download 164525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // may be a part of initialization. 165525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int INIT_WATCHDOG_MS = 90000; 166525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 167525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for routing to be applied before watchdog 168525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off 169525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int ROUTING_WATCHDOG_MS = 10000; 170525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1713e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Amount of time to wait before closing the NFCEE connection 1723e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // in a disable/shutdown scenario. 1733e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_OPERATIONS_MS = 5000; 1743e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Polling interval for waiting on NFCEE operations 1753e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_POLL_MS = 100; 1763e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 17731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen // Default delay used for presence checks 17831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen static final int DEFAULT_PRESENCE_CHECK_DELAY = 125; 17931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 180d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 181d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 182d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 183d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 184d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 18549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 18649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 18749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 18849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 18949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 19049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 19149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 19249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 19396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_UP = 19496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_UP"; 19596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 19696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_DOWN = 19796e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_DOWN"; 19896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 1992c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 2002c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 2012c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 2022c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 2032c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 2042c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 2052c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 2062c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 2072c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 2082c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 2092c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 2102c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 2112c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 212525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_ACTIVATED = 213525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED"; 214525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_DEACTIVATED = 215525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED"; 21649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 21749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 21849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 2190bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 22049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 221c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen private final ReaderModeDeathRecipient mReaderModeDeathRecipient = 222c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen new ReaderModeDeathRecipient(); 22349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 2240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 225d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 226d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 227d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 2282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 229fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 230525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // mSePackages holds packages that accessed the SE, but only for the owner user, 231525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // as SE access is not granted for non-owner users. 232fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly HashSet<String> mSePackages = new HashSet<String>(); 233fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 2347d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 235fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 236fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing 237fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling 2389f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen boolean mHostRouteEnabled; // current Device Host state of host-based routing 239c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen boolean mReaderModeEnabled; // current Device Host state of reader mode 24031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams mReaderModeParams; 24131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 242e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 24331949217328bf2357ff044f0d18677fe588c790cNick Pelly 24431949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 24531949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 24631949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 24731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 2482f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 2492f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 25005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 2514a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 2520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2530e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 254525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mRoutingWakeLock; 255525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mEeWakeLock; 256525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 257d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 258d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 259d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 260d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 26177d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2624a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2634a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2644a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 265a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen CardEmulationService mCardEmulationService; 26631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 26731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 26896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen boolean mIsDebugBuild; 2690a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen boolean mIsHceCapable; 270c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfceeAccessControl mNfceeAccessControl; 2712ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 27276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 273fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 274275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 2757d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private HandoverManager mHandoverManager; 2767d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private ContentResolver mContentResolver; 27778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen private RegisteredAidCache mAidCache; 2789f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen private HostEmulationManager mHostEmulationManager; 279d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen private AidRoutingManager mAidRoutingManager; 280d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 281d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 282d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 28393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 284c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 28593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 28693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 28789c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen public static void validateUserId(int userId) { 28889c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen if (userId != UserHandle.getCallingUserId()) { 28989c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen throw new SecurityException("userId passed in it not the calling user."); 29089c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen } 29189c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen } 29289c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen 293c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void enforceNfceeAdminPerm(String pkg) { 294c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (pkg == null) { 295c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException("caller must pass a package name"); 296c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 297c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 298c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) { 299c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH + 300c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton " denies NFCEE access to " + pkg); 301c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 302525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { 303525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project throw new SecurityException("only the owner is allowed to call SE APIs"); 304525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 30593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 30693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 307d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 308d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 309d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 3110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 312f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 313f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 314f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 315f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 316f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 317f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 318f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 319d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 320f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 321a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3220a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 3230a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 324f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 325f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 326f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 327f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 328f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 329d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 330f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 331a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3320a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_CARD_EMULATION, aid); 3330a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 334f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 335f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 336f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 3379f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen * Notifies transaction 3389f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen */ 3399f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3409f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationActivated() { 3410a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3420a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyHostEmulationActivated(); 3430a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3449f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3459f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3469f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3479f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationData(byte[] data) { 3480a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3490a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyHostEmulationData(data); 3500a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3519f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3529f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3539f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3549f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationDeactivated() { 3550a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3560a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyNostEmulationDeactivated(); 3570a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3589f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3599f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3609f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen /** 361f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 362f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 363f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 364f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 365f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 366f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 367f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 368f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 369f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 370f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 371d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 372f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 373f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 374f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 375f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 37657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen /** 37757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen * Notifies P2P Device detected, first packet received over LLCP link 37857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen */ 37957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 38057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 38157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 38257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 38357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 384d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 385f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 386a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3870a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 3880a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 389f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 390f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 391d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 392f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 393a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3940a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 3950a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 396f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 397f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 398f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 399525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenActivated() { 400a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4010a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null); 4020a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 403525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 404525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 405525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 406525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenDeactivated() { 407a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4080a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null); 4090a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 410525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 411525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 412525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 413525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 414442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 415a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4160a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 4170a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 418442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 419442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 420442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 421442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 422a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4230a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 4240a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 425442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 426442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 427442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 428442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 429a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4300a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 4310a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 432442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 433442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 43431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen final class ReaderModeParams { 43531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int flags; 43631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public IAppCallback callback; 43731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int presenceCheckDelay; 43831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 43931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 440525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public NfcService(Application nfcApplication) { 4414a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 4424a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 443ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 444a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen mCardEmulationService = new CardEmulationService(); 4454a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 4462f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 4472f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 448d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 449d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 450525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext = nfcApplication; 4517d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mContentResolver = mContext.getContentResolver(); 452525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost = new NativeNfcManager(mContext, this); 45374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 4547d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager = new HandoverManager(mContext); 4557d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean isNfcProvisioningEnabled = false; 4567d8987f233985a5ff29226890e11012275d325f5Martijn Coenen try { 4577d8987f233985a5ff29226890e11012275d325f5Martijn Coenen isNfcProvisioningEnabled = mContext.getResources().getBoolean( 4587d8987f233985a5ff29226890e11012275d325f5Martijn Coenen R.bool.enable_nfc_provisioning); 4597d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } catch (NotFoundException e) { 4607d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 4617d8987f233985a5ff29226890e11012275d325f5Martijn Coenen 4627d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (isNfcProvisioningEnabled) { 4637d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 4647d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 4657d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else { 4667d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = false; 4677d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 468525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 4697d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(!mInProvisionMode); 4707d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode); 4717d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager, 472525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 47324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 47437058bf7b59def2f9a565ae5b16aae54e80e9e95Sunil Jogi mSecureElement = new NativeNfcSecureElement(mContext); 475eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 4760bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 477525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mNfceeAccessControl = new NfceeAccessControl(mContext); 478c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 479525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 4800e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 481f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 48231949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 4830b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 484f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 48596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); 48696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 487525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 488525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 489525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock = mPowerManager.newWakeLock( 490525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 491525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock = mPowerManager.newWakeLock( 492525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock"); 493275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 494525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 495fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = checkScreenState(); 496533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 497d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 499525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents for all users 500eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 50165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 50265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 503275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 5043859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen filter.addAction(Intent.ACTION_USER_SWITCHED); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 506525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 5070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 5080a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen PackageManager pm = mContext.getPackageManager(); 509341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION); 5100a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 5110a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mAidRoutingManager = new AidRoutingManager(); 512451ba48faa87d78bfbec0597ff06af1747cf6acbMartijn Coenen mAidCache = new RegisteredAidCache(mContext, mAidRoutingManager); 51378976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen mHostEmulationManager = new HostEmulationManager(mContext, mAidCache); 514a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen } 515a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 5160a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 5170a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 5180a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 5190a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 5200a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5210a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 5220a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5230a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter = new IntentFilter(); 5240a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 5250a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 5260a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addDataScheme("package"); 5270a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5280a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 5290a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5300a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen updatePackageCache(); 5310a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 532e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 53331949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 53531949217328bf2357ff044f0d18677fe588c790cNick Pelly 536d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 537d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 538d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 539d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 540525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 541525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 542525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 543d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 544d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 545d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 546d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 547d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 548d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 549d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 550d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 551d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 552d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 553d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 554d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 555d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 5577d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String airplaneModeRadios = Settings.System.getString(mContentResolver, 5587d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_RADIOS); 5597d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String toggleableRadios = Settings.System.getString(mContentResolver, 5607d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 5637d8987f233985a5ff29226890e11012275d325f5Martijn Coenen airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 5657d8987f233985a5ff29226890e11012275d325f5Martijn Coenen toggleableRadios.contains(Settings.Global.RADIO_NFC); 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly 572e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen void updatePackageCache() { 573525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PackageManager pm = mContext.getPackageManager(); 574525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER); 575e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (this) { 576e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mInstalledPackages = packages; 577e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 578e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 579e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 580fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int checkScreenState() { 581fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (!mPowerManager.isScreenOn()) { 582fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_OFF; 583fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (mKeyguard.isKeyguardLocked()) { 584fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_LOCKED; 585fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 586fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_UNLOCKED; 587fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 588fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 589fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 590525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int doOpenSecureElementConnection() { 591525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 592525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 593525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doOpenSecureElementConnection(); 594525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 595525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 596525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 597525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 598525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 599525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceive(int handle, byte[] cmd) { 600525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 601525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 602525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceiveNoLock(handle, cmd); 603525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 604525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 605525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 606525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 607525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 608525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceiveNoLock(int handle, byte[] cmd) { 609525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doTransceive(handle, cmd); 610525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 611525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 612525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project void doDisconnect(int handle) { 613525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 614525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 615525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mSecureElement.doDisconnect(handle); 616525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 617525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 618525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 619525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 620525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 62331949217328bf2357ff044f0d18677fe588c790cNick Pelly * 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 62731949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 62831949217328bf2357ff044f0d18677fe588c790cNick Pelly * 62931949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 63031949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 63131949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 63231949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 63331949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 63431949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 63531949217328bf2357ff044f0d18677fe588c790cNick Pelly * 63631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 63731949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 63831949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 63931949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 64031949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 64131949217328bf2357ff044f0d18677fe588c790cNick Pelly * 64231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 64331949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 64431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 64531949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 64631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 64731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 64831949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 64931949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 65031949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 65131949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 65331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 65431949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 65631949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 65731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 65831949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 65931949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 66031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 66131949217328bf2357ff044f0d18677fe588c790cNick Pelly 6624467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 6634467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 6644467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 6654467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 6664467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 6674467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 6684467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 6694467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 6704467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 67131949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 67231949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 67331949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 67431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 67531949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 67631949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 67731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 67831949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 6790fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 6801668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 68131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 6821668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 6830fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 68431949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 6850fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 6860fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 6870fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 688efb7a3df560585994cebd40fcf5ffbc864f8c358Martijn Coenen // Build initial AID cache even if NFC is off 689341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 69043dc7d3d2160c5fbd063e27c2810b87f4626e75fMartijn Coenen mAidCache.invalidateCache(ActivityManager.getCurrentUser()); 69143dc7d3d2160c5fbd063e27c2810b87f4626e75fMartijn Coenen } 69231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 69331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 69431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 69531949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 69631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 69731949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 69831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 69931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 70031949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 70131949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 70231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 70331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 704d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 705d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 706d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 70731949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 70831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 70931949217328bf2357ff044f0d18677fe588c790cNick Pelly 71031949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 71131949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 71231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 71331949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 71431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 71531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 71631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 71731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 71831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 71931949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 72031949217328bf2357ff044f0d18677fe588c790cNick Pelly 721525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 722525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.start(); 723525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 724525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 725525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 726525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (!mDeviceHost.initialize()) { 727525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Error enabling NFC"); 728525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project updateState(NfcAdapter.STATE_OFF); 729525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return false; 730525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 731525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 732525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 733525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 734525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 735525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.cancel(); 73631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 73731949217328bf2357ff044f0d18677fe588c790cNick Pelly 7380a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 7390a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen // Generate the initial card emulation routing table 740f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenen mAidCache.onNfcEnabled(); 7410a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 742d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 74331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 74431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 7450b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 74631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 74731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 74831949217328bf2357ff044f0d18677fe588c790cNick Pelly 749d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 750d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 75131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 7520c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 753fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 75431949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 75531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 75631949217328bf2357ff044f0d18677fe588c790cNick Pelly 75731949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 75831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 75931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 76031949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 76131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 76231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 76331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 76431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 76531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 76631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 76731949217328bf2357ff044f0d18677fe588c790cNick Pelly 76831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 76931949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 77031949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 77131949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 772525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 77331949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 77431949217328bf2357ff044f0d18677fe588c790cNick Pelly 775953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen if (mIsHceCapable) { 776f5cd84c3a7ffb66196ab3c0745569da937d7533bMartijn Coenen mAidCache.onNfcDisabled(); 777953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen } 778d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 77977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 78031949217328bf2357ff044f0d18677fe588c790cNick Pelly 7813e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen /* The NFC-EE may still be opened by another process, 7823e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * and a transceive() could still be in progress on 7833e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * another Binder thread. 7843e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * Give it a while to finish existing operations 7853e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * before we close it. 7863e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen */ 7873e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Long startTime = SystemClock.elapsedRealtime(); 7883e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen do { 7893e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen synchronized (NfcService.this) { 7903e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen if (mOpenEe == null) 7913e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen break; 7923e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 7933e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen try { 7943e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Thread.sleep(WAIT_FOR_NFCEE_POLL_MS); 7953e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } catch (InterruptedException e) { 7963e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Ignore 7973e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 7983e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } while (SystemClock.elapsedRealtime() - startTime < WAIT_FOR_NFCEE_OPERATIONS_MS); 7993e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 8004ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen synchronized (NfcService.this) { 8014ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (mOpenEe != null) { 8024ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen try { 8034ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen _nfcEeClose(-1, mOpenEe.binder); 8044ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } catch (IOException e) { } 8054ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 8064ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 8074ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen 80831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 80931949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 81031949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 81131949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 81231949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 81331949217328bf2357ff044f0d18677fe588c790cNick Pelly 8140b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 81531949217328bf2357ff044f0d18677fe588c790cNick Pelly 81631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 81731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 81831949217328bf2357ff044f0d18677fe588c790cNick Pelly 81931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 82031949217328bf2357ff044f0d18677fe588c790cNick Pelly 82131949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 82231949217328bf2357ff044f0d18677fe588c790cNick Pelly 823d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 824d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 82531949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 82631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 82731949217328bf2357ff044f0d18677fe588c790cNick Pelly 82831949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 82931949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 830525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[][]apdus = mDeviceHost.getWipeApdus(); 831525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 832525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (apdus == null) { 833525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.d(TAG, "No wipe APDUs found"); 834525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 835525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 83631949217328bf2357ff044f0d18677fe588c790cNick Pelly 83731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 838525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Hold a wake-lock over the entire wipe procedure 839525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 840525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 841525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable && !enableInternal()) { 842ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 84331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 844f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 845525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 846525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // NFC enabled 847525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = 0; 848525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 849525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "Executing SE wipe"); 850525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project handle = doOpenSecureElementConnection(); 8512b4dc11f4508cdb662a8069cccf9f2273004a4c8Martijn Coenen if (handle < 0) { 852525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Could not open the secure element"); 853525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 854525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 855525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // TODO: remove this hack 856525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 857525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Thread.sleep(1000); 858525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 859525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Ignore 860525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 86131949217328bf2357ff044f0d18677fe588c790cNick Pelly 862525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 863525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 864525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (byte[] cmd : apdus) { 865525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] resp = doTransceiveNoLock(handle, cmd); 866525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (resp == null) { 867525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 868525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 869525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 870525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 871525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 872525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.resetTimeouts(); 873525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 874525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 8752b4dc11f4508cdb662a8069cccf9f2273004a4c8Martijn Coenen if (handle >= 0) { 876525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(handle); 877525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 878525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 879525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 880525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable) { 881525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project disableInternal(); 882525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 883ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 884525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 885525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 88631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 887525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "SE wipe done"); 88831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 88931949217328bf2357ff044f0d18677fe588c790cNick Pelly 89031949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 8912a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 89231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 89331949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 89431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 89531949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 89631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 89731949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 89831949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 899525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 90031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 90131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 90231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 90331949217328bf2357ff044f0d18677fe588c790cNick Pelly 90431949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 90531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 90631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 90731949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 90831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 9090e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 9100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 911d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 912d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 913d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 914d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 915d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 916d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 917d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 918d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 919d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 920d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 921d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 922d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 923d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 924d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 925d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 926d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 927d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 928d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 929d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 930d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 9310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 9324a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 933fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9340e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 93593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 9360e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 93731949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 9381668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 9391668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 9401668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 9411668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 9421668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 9431668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 9441668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 9451668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 9461668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 94831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 94931949217328bf2357ff044f0d18677fe588c790cNick Pelly 95031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 953fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 954290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 95593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 9560e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 957290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 958290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 959290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 960290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 96131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 96231949217328bf2357ff044f0d18677fe588c790cNick Pelly 96331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 966fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9670b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 96831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 9699993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 97031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 971d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 972d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 973d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9740b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 975d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 976d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 9770b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 97831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 97931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 9800b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 9810b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 98231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 9830b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 98431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 98577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 986d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 987d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 988d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 989d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 990d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 991d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9920b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 993d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 994d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 9950b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 99631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 99731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 9980b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 9990b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 100031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 10010b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 100231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 100377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 1004d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 1005d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 1006d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 1007d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 1008d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 1009d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 10100b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 101124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 101205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1013a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 10140b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 10150b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 10160b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 10170b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 1018ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 1019a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 1020a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 1021a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 1022a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 1023a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 1024a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 1025a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 1026a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 1027a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 1028a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1029a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1030a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1031a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1032a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 103324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 103424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 103524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 103624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 103724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 103849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 10390b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 10402094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 10412094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 10422094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 104331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setAppCallback(IAppCallback callback) { 1044ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10453859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 1046ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 1047ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 1048ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 10490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 10500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 10510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 10520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1053fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1054c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) { 1055c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 105649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 10570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 10580bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1059fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1060a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public INfcCardEmulation getNfcCardEmulationInterface() { 1061a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return mCardEmulationService; 1062a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1063a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1064a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 106531949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 106631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 106731949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 106831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 106931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 107031949217328bf2357ff044f0d18677fe588c790cNick Pelly 107131949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 107231949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 107331949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 10740e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1075391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 1076391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 1077ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 1078391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly enforceAdminPerm(mContext); 1079ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 1080391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 10810c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 10820c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 10830c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 10840c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen enforceAdminPerm(mContext); 10850c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 10860c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 10870c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 10880c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.disableDiscovery(); 10890c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.enableDiscovery(); 10900c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 1091c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 1092c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 109331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras) 109431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen throws RemoteException { 1095c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 1096c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen if (flags != 0) { 1097c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 109831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = new ReaderModeParams(); 109931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.callback = callback; 110031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.flags = flags; 110131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.presenceCheckDelay = extras != null ? 110231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 110331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen DEFAULT_PRESENCE_CHECK_DELAY)) : DEFAULT_PRESENCE_CHECK_DELAY; 1104c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.linkToDeath(mReaderModeDeathRecipient, 0); 1105c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (RemoteException e) { 1106c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Remote binder has already died."); 1107c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen return; 1108c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1109c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } else { 1110c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 111131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 1112c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.unlinkToDeath(mReaderModeDeathRecipient, 0); 1113c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (NoSuchElementException e) { 1114c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Reader mode Binder was never registered."); 1115c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1116c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1117c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 1118c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1119c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1120c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1121c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 1122c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen final class ReaderModeDeathRecipient implements IBinder.DeathRecipient { 1123c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 1124c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen public void binderDied() { 1125c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 112631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (mReaderModeParams != null) { 112731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 1128c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 1129c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1130c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1131c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1132c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 11330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1134a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen final class CardEmulationService extends INfcCardEmulation.Stub { 1135a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1136a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public boolean isDefaultServiceForCategory(int userId, ComponentName service, 1137a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen String category) throws RemoteException { 1138a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1139a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1140a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 114189c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 114289c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen validateUserId(userId); 114306645f1a5dc19e01f61895797f7b4c2204ae7b62Martijn Coenen return mAidCache.isDefaultServiceForCategory(userId, category, service); 1144a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1145a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1146a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 114789c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen public boolean isDefaultServiceForAid(int userId, ComponentName service, String aid) 114889c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen throws RemoteException { 114989c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen if (!mIsHceCapable) { 115089c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen return false; 115189c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen } 115289c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen validateUserId(userId); 115389c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 115478976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen return mAidCache.isDefaultServiceForAid(userId, service, aid); 115589c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen } 115689c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen 115789c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen @Override 1158a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public boolean setDefaultServiceForCategory(int userId, ComponentName service, 1159a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen String category) throws RemoteException { 1160a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1161a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1162a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 116389c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen validateUserId(userId); 116489c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen enforceAdminPerm(mContext); 116578976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen return mAidCache.setDefaultServiceForCategory(userId, service, category); 1166a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 116775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen 116875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen @Override 116975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen public boolean setDefaultForNextTap(int userId, ComponentName service) 117075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen throws RemoteException { 117175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen if (!mIsHceCapable) { 117275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen return false; 117375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen } 117489c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen validateUserId(userId); 117589c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen enforceAdminPerm(mContext); 117689c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen mHostEmulationManager.setDefaultForNextTap(service); 117778976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen return mAidCache.setDefaultForNextTap(userId, service); 117875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen } 117975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen 1180a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1181a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public List<ApduServiceInfo> getServices(int userId, String category) 1182a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen throws RemoteException { 1183a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1184a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return null; 1185a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 118689c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen validateUserId(userId); 118789c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen enforceAdminPerm(mContext); 118878976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen return mAidCache.getServicesForCategory(userId, category); 1189a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1190a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen }; 1191a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 11924a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 1193fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 1195d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1196bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1197f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 119931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1204f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1206b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 1207b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 120821545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 1209b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 1212fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1216fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1217ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 1218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1219bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1220f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 122231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1227f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1228b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1229b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1231ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 1232cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 1233cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1234cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 1235cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 1236ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 1237ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 1238ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 1239ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 1240ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 1241ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 1242ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1243ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1246fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1247aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 1248aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1249aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1251aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1252aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 125331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1254aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 1255aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1256aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1257aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 1258f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1259aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 1260aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 1261aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 1262aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 1263aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1264aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1265aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1266aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1267aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1268aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1269aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 1270b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 1271d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1272bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1273f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 127431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1277f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1278f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1279f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1280f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1281b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 1282f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1283f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1284f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1286fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1287b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 1288f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1289b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1290b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 129131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1292b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1293b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1294b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1295b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 1296f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1297b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1298b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1299b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1300b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1301ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 1302b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1303b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1304fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 1306182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1307182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 1308f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 131131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 13122c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1316f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 13173ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 13182c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 13192c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1320f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 132170bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 1322f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1324fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13259d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 132697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 1327d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1328bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1329f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1330f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 1331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 133331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1335f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1336f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1337f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1338f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1339f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1340bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 1341bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1342bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1343bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 13449d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 13459d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 1346bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 1347bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 1348bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 1349bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 1350bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 1351bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 1352bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 1353bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1354bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 1355f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1356f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1357f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1359fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1361d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1362bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1363f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1364f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1365f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 136631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1367f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1369f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1371f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1373f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1374f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1375f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1376f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1379f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1380f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1381f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1383f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1384f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1385f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1386f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1387f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1388fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13893fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1390d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1391bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1392f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1393f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1394f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 139531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1396f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1397f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1398f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1399f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1400f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1401f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1402f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1403f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1404f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1405791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1406791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1407f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1408f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1409f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1410f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1412f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1413f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1414f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1415fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 14163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 14173fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1420fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 14213fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 142203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 142303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1424f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 142503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 142603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 142731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 142803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 142903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 143003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 143103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1432f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 143303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 143403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 143503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 143603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1437f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 143803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1439f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 144003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 144103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1442f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1443f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 14440aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 14450aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 14460aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 14470aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1448f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 14490aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 14500aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 145131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 14520aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 14530aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 14540aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 14550aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1456f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 14570aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 14580aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 14590aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 14600aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 14610aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 14620aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1463f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 14640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 14650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 14660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 14670aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 14681b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 14693fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 14703fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 14713fb14d0868594c78a777e805545209636814e223Martijn Coenen 1472f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 14733fb14d0868594c78a777e805545209636814e223Martijn Coenen 14743fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 147531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 14763fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 14773fb14d0868594c78a777e805545209636814e223Martijn Coenen } 14783fb14d0868594c78a777e805545209636814e223Martijn Coenen 14793fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1480f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 14813fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 14823fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 14833fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 14843fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 14853fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 14863fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 14873fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 14883fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 14893fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 14903fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 14913fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1492391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 14933fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 14943fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 14954a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 14963fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 14973fb14d0868594c78a777e805545209636814e223Martijn Coenen } 14983fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 14993fb14d0868594c78a777e805545209636814e223Martijn Coenen } 15003fb14d0868594c78a777e805545209636814e223Martijn Coenen 15011b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1502fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 15031b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1504f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1505fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1506fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1507fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1508fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1509fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1510dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1511dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1512dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1513358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1514358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1515358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1516358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1517358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1518358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1519358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1520dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1521dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1522dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1523f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 15241b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1525bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1526bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1527bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1528bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1529bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1530bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1531bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1532bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1533bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1534bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1535ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1536ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1537ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1538ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1539ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1540c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1541f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 154292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly void _nfcEeClose(int callingPid, IBinder binder) throws IOException { 1543dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1544dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1545dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1546dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 15470571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly synchronized (NfcService.this) { 15484ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1549dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1550dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1551dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1552dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1553dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 155492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (callingPid != -1 && callingPid != mOpenEe.pid) { 1555dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1556dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 155792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (mOpenEe.binder != binder) { 155892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly throw new SecurityException("Wrong binder handle"); 155992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 1560dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 156192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly binder.unlinkToDeath(mOpenEe, 0); 1562f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1563525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(mOpenEe.handle); 1564dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1565dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1566fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1567dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1568dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1569dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 15704a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 157149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 157249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 157349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 157449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 157549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1576c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1577c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private Bundle writeEeException(int exceptionType, String message) { 157849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 1579c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putInt("e", exceptionType); 1580c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putString("m", message); 158149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 158249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15830bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1584bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1585c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle open(String pkg, IBinder b) throws RemoteException { 1586c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1587bd555ee64250126b60b24814120a2049943920caNick Pelly 158849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 1589c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen int handle = _open(b); 1590c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1591c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(handle, "NFCEE open exception."); 1592c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen } else { 159349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 15940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 159549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 159649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15970bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1598c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen /** 1599c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * Opens a connection to the secure element. 1600c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * 1601c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * @return A handle with a value >= 0 in case of success, or a 1602c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * negative value in case of failure. 1603c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen */ 1604c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private int _open(IBinder b) { 160549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 160631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1607c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_NFC_DISABLED; 160849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16097a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen if (mInProvisionMode) { 16107a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // Deny access to the NFCEE as long as the device is being setup 16117a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen return EE_ERROR_IO; 16127a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen } 16137a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen if (mDeviceHost.enablePN544Quirks() && mP2pLinkManager.isLlcpActive()) { 16147a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // Don't allow PN544-based devices to open the SE while the LLCP 16157a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // link is still up or in a debounce state. This avoids race 16167a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // conditions in the NXP stack around P2P/SMX switching. 16177a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen return EE_ERROR_EXT_FIELD; 16187a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen } 161949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 1620c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_ALREADY_OPEN; 162149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1623476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen boolean restorePolling = false; 1624476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen if (mDeviceHost.enablePN544Quirks() && mNfcPollingEnabled) { 1625476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // Disable polling for tags/P2P when connecting to the SMX 1626476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // on PN544-based devices. Whenever nfceeClose is called, 1627476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // the polling configuration will be restored. 1628476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mDeviceHost.disableDiscovery(); 1629476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mNfcPollingEnabled = false; 1630476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen restorePolling = true; 1631476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen } 1632476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen 1633525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = doOpenSecureElementConnection(); 1634c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1635476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen 1636476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen if (restorePolling) { 1637476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mDeviceHost.enableDiscovery(); 1638476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mNfcPollingEnabled = true; 1639476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen } 1640c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 164149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1642525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000); 1643ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 164492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle, b); 164549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 164649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 164749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 164849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 164949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 165084e1e0adc2516afd35ebab029a52e764e0490559Jason parks 165184e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 165284e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 1653525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) { 165484e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 165584e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 1656c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1657c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 165849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 16600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1661bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 166292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public Bundle close(String pkg, IBinder binder) throws RemoteException { 1663c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1664c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 166549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 166649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 166792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(getCallingPid(), binder); 166849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 166949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1670c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 16710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 167249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 167349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1675bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1676c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle transceive(String pkg, byte[] in) throws RemoteException { 1677c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1678bd555ee64250126b60b24814120a2049943920caNick Pelly 167949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 168049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 168149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 168249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 168349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 168449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 168549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1686c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 16870bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 168849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 168949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1691c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private byte[] _transceive(byte[] data) throws IOException { 169249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 169331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 169449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 169549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16960571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly if (mOpenEe == null) { 169749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 169849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 169949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 170049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 170149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 17020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17030bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1704525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceive(mOpenEe.handle, data); 17050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1707bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1708c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public int getCardEmulationRoute(String pkg) throws RemoteException { 1709c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 171049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 17110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17120bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1713bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1714c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void setCardEmulationRoute(String pkg, int route) throws RemoteException { 1715c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 171649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 1717525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask(); 1718525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.execute(); 1719525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 1720525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Block until route is set 1721525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.get(); 1722525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 1723525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1724525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 1725525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1726525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 17270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1728bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1729bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1730c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void authenticate(String pkg, byte[] token) throws RemoteException { 1731c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1732bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1733525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1734525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 1735525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public String getDriverName(String pkg) throws RemoteException { 1736525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NfcService.this.enforceNfceeAdminPerm(pkg); 1737525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mDeviceHost.getName(); 1738525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1739c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 17400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 174149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 174249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 174349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 174492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // binder handle used for DeathReceipient. Must keep 174592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // a reference to this, otherwise it can get GC'd and 174692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // the binder stub code might create a different BinderProxy 174792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // for the same remote IBinder, causing mismatched 174892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // link()/unlink() 174992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public IBinder binder; 175049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 175192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public OpenSecureElement(int pid, int handle, IBinder binder) { 175249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 175349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 175492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly this.binder = binder; 175549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1756bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 175749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 175849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 175992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly Log.i(TAG, "Tracked app " + pid + " died"); 176049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 17610bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 176292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(-1, binder); 1763dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 17640bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 176692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly @Override 176792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public String toString() { 176892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=") 176992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly .append(pid).append(" handle=").append(handle).append("]").toString(); 177092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 17710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 17739a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 17749a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 17759a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 17769a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 17779a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 17789a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1782e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1783aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1784aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 178531949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 1786a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project final Object mCancelWaiter = new Object(); 1787525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project final int mTimeout; 1788a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project boolean mCanceled = false; 1789525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1790525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public WatchDogThread(String threadName, int timeout) { 1791525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project super(threadName); 1792525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mTimeout = timeout; 1793525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1794525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 17952edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 17962edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 1797a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project try { 1798a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1799a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.wait(mTimeout); 1800a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project if (mCanceled) { 1801a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project return; 1802a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 18032edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1804a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } catch (InterruptedException e) { 1805a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project // Should not happen; fall-through to abort. 1806a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.w(TAG, "Watchdog thread interruped."); 1807a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project interrupt(); 18082edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1809a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.e(TAG, "Watchdog triggered, aborting."); 1810a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mDeviceHost.doAbort(); 18112edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1812a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project 18132edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 1814a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1815a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCanceled = true; 1816a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.notify(); 1817a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 18182edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 18192edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 18202edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 18219f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen static byte[] hexStringToBytes(String s) { 18229f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (s == null || s.length() == 0) return null; 18239f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen int len = s.length(); 18249f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (len % 2 != 0) { 18259f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen s = '0' + s; 18269f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen len++; 18279f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18289f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen byte[] data = new byte[len / 2]; 18299f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen for (int i = 0; i < len; i += 2) { 18309f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 18319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen + Character.digit(s.charAt(i+1), 16)); 18329f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18339f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return data; 18349f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18359f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1836fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1837fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1838fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1839fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1840e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 18419a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) { 1842fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // PN544 cannot be reconfigured while EE is open 1843e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1844e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1845525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 18467d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (mInProvisionMode) { 18477d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 18487d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 18497d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mInProvisionMode) { 18507d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Notify dispatcher it's fine to dispatch to any package now 18517d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // and allow handover transfers. 18527d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher.disableProvisioningMode(); 18537d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(true); 18547d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 18557d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1856f439271150e4548f116919e0254d57655421581cMartijn Coenen try { 1857f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.start(); 1858f439271150e4548f116919e0254d57655421581cMartijn Coenen 1859525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) { 1860f439271150e4548f116919e0254d57655421581cMartijn Coenen /* TODO undo this after the LLCP stack is fixed. 1861f439271150e4548f116919e0254d57655421581cMartijn Coenen * Use a different sequence when turning the screen off to 1862f439271150e4548f116919e0254d57655421581cMartijn Coenen * workaround race conditions in pn544 libnfc. The race occurs 1863f439271150e4548f116919e0254d57655421581cMartijn Coenen * when we change routing while there is a P2P target connect. 1864f439271150e4548f116919e0254d57655421581cMartijn Coenen * The async LLCP callback will crash since the routing code 1865f439271150e4548f116919e0254d57655421581cMartijn Coenen * is overwriting globals it relies on. 1866f439271150e4548f116919e0254d57655421581cMartijn Coenen */ 1867f439271150e4548f116919e0254d57655421581cMartijn Coenen if (POLLING_MODE > SCREEN_STATE_OFF) { 1868f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1869f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF, disconnect"); 1870f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1871f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1872f439271150e4548f116919e0254d57655421581cMartijn Coenen maybeDisconnectTarget(); 1873f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1874f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1875f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1876f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1877f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE OFF"); 1878f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = false; 1879f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doDeselectSecureElement(); 1880f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1881fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1882f439271150e4548f116919e0254d57655421581cMartijn Coenen return; 1883fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1884f439271150e4548f116919e0254d57655421581cMartijn Coenen 18850a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable && mScreenState >= SCREEN_STATE_ON_LOCKED && 1886d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mAidRoutingManager.aidsRoutedToHost()) { 1887d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen if (!mHostRouteEnabled || force) { 1888d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHostRouteEnabled = true; 1889d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.enableRoutingToHost(); 1890d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1891d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } else { 1892d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen if (force || mHostRouteEnabled) { 1893d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHostRouteEnabled = false; 1894d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.disableRoutingToHost(); 18959f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18969f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18979f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1898f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-EE routing 1899f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= SCREEN_STATE_ON_LOCKED && 1900f439271150e4548f116919e0254d57655421581cMartijn Coenen mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1901f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfceeRouteEnabled) { 1902f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE ON"); 1903f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = true; 1904f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doSelectSecureElement(); 1905f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1906f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1907f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1908fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1909fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1910fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.doDeselectSecureElement(); 1911fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1912fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1913fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1914f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-C polling 1915f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= POLLING_MODE) { 1916f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfcPollingEnabled) { 1917f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C ON"); 1918f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = true; 1919f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.enableDiscovery(); 1920f439271150e4548f116919e0254d57655421581cMartijn Coenen } 192131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (mReaderModeParams != null && !mReaderModeEnabled) { 1922c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen mReaderModeEnabled = true; 192331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mDeviceHost.enableReaderMode(mReaderModeParams.flags); 1924c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 192531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (mReaderModeParams == null && mReaderModeEnabled) { 1926c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen mReaderModeEnabled = false; 1927c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen mDeviceHost.disableReaderMode(); 1928c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 19297d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else if (mInProvisionMode && mScreenState >= SCREEN_STATE_ON_LOCKED) { 19307d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Special case for setup provisioning 19317d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mNfcPollingEnabled) { 19327d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Log.d(TAG, "NFC-C ON"); 19337d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcPollingEnabled = true; 19347d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mDeviceHost.enableDiscovery(); 19357d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1936f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1937f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1938f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF"); 1939c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen if (mReaderModeEnabled) { 1940c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen mReaderModeEnabled = false; 1941c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen mDeviceHost.disableReaderMode(); 1942c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1943f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1944f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1945f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1946fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1947f439271150e4548f116919e0254d57655421581cMartijn Coenen } finally { 1948f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.cancel(); 1949221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 195065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 195165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 195265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 19532436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 195431949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 19559a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1956a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1957a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 195831949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 195931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 196031949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 196131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 196231949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 196331949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 196431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 196531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 196631949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 196731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 196831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 196931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 197031949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 197131949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 197231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 197331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 197431949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 197531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 197631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 197731949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 197831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 197931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 198031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1981bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1982bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1983bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1984bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1985bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 198631949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 198731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 198831949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 198931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 199031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 19912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 199231949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 19930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 199631949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 199731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 199831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2000b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 2001b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 200231949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 200331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 200431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 200531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 2006f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2007f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2008d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 20094a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 2010c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 20114a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 2012d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 2013d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 2014d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 20153b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 2016e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 20173b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 2018e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 2019e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 2020e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen /** For use by code in this process */ 20214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 2022c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 20234a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 2024d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 2025d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 202657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 2027b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 202857d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 202957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 2030d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void routeAids(String aid, int route) { 2031d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen Message msg = mHandler.obtainMessage(); 2032d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.what = MSG_ROUTE_AID; 2033d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.arg1 = route; 2034d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.obj = aid; 2035d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendMessage(msg); 2036d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 2037d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 2038d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void unrouteAids(String aid) { 2039d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen sendMessage(MSG_UNROUTE_AID, aid); 2040d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 2041d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 2042d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void commitRouting() { 2043d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING); 2044d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 2045d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 20469f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public boolean sendData(byte[] data) { 20479f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return mDeviceHost.sendRawFrame(data); 20489f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 20499f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2050b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 2051b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 2052b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 2053b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 2054b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 2055b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 2056b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 20573fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 2058b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 2059b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 206031949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 2061d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_ROUTE_AID: { 2062d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen int route = msg.arg1; 2063d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 2064d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.routeAid(hexStringToBytes(aid), route); 2065d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen // Restart polling config 2066d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 2067d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 2068d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_UNROUTE_AID: { 2069d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 2070d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.unrouteAid(hexStringToBytes(aid)); 2071d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 2072d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 2073d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_COMMIT_ROUTING: { 2074d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen applyRouting(true); 2075d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 2076d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 207731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 207831949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 207931949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 208031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 208131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 208231949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 208331949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 208431949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 208531949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 208631949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 208731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 208831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 2089ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag); 209031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 2091d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 209277d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 2093d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 209431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 209531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 209631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 209757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 209831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 209931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 210031949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 210131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams readerParams = null; 210231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY; 2103c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 210431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen readerParams = mReaderModeParams; 2105c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 210631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (readerParams != null) { 210731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen presenceCheckDelay = readerParams.presenceCheckDelay; 210831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) { 210931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode"); 211031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen tag.startPresenceChecking(presenceCheckDelay); 211131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 211231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen break; 211331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 211431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 211531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (readerParams == null || 211631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 211731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_START); 2118c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 211989baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 212089baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // When these tags start containing NDEF, they will require 212189baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // the stack to deal with them in a different way, since 212289baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // they are activated only really shortly. 212389baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // For now, don't consider NDEF on these. 212489baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 212531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen tag.startPresenceChecking(presenceCheckDelay); 212631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 212789baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen break; 212889baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen } 2129391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 2130c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 2131391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 213231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen tag.startPresenceChecking(presenceCheckDelay); 213331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 213431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 213531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 213631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen tag.startPresenceChecking(presenceCheckDelay); 213731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 213831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 213931949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 2140d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 214131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 214231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 214331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 214431949217328bf2357ff044f0d18677fe588c790cNick Pelly 214531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 214631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 2147f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen /* Tell the host-emu manager an AID has been selected on 2148f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen * a secure element. 2149f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen */ 2150f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen if (mHostEmulationManager != null) { 2151f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen mHostEmulationManager.notifyOffHostAidSelected(); 2152f9366de7b3ad1ce90859d4194dacf13c0066926bMartijn Coenen } 215331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 215431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 215531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 215631949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 215731949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 215831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 215914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 216031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 216131949217328bf2357ff044f0d18677fe588c790cNick Pelly 216231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 216331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 216431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 216531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 216631949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 216731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 216814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 216931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 217031949217328bf2357ff044f0d18677fe588c790cNick Pelly 217131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 217231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 217331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 217431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 217531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 217631949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 217731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 217831949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 217931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 218031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 218114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 218231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 218331949217328bf2357ff044f0d18677fe588c790cNick Pelly 218431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 218531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 218631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 218731949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 218831949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 218931949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 219031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 219131949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 219231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 219331949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 219431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 219531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 219614a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 219731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 2198c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 219931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 220096e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 220196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent actIntent = new Intent(ACTION_LLCP_UP); 220296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(actIntent); 220396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 220431949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 220531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 220631949217328bf2357ff044f0d18677fe588c790cNick Pelly 220731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 220896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 220996e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent deactIntent = new Intent(ACTION_LLCP_DOWN); 221096e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(deactIntent); 221196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 221231949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 221331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 221431949217328bf2357ff044f0d18677fe588c790cNick Pelly 221531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 221631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 221731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 221831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 221931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 222031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 222131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 222231949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 222331949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 222431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 222531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 222631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 222731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 222831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 222931949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 223031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 223131949217328bf2357ff044f0d18677fe588c790cNick Pelly 223277d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 223331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 223457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen case MSG_LLCP_LINK_FIRST_PACKET: 223557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mP2pLinkManager.onLlcpFirstPacketReceived(); 223657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen break; 223731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 223831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 223931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 224031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 224131949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 224231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 224331949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 224431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 224531949217328bf2357ff044f0d18677fe588c790cNick Pelly 224631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 224731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 224831949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 224931949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 225014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 225131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 225231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 225331949217328bf2357ff044f0d18677fe588c790cNick Pelly 225431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 225531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 225631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 225731949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 225814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 225931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 226031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 226131949217328bf2357ff044f0d18677fe588c790cNick Pelly 2262525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_ACTIVATED: { 2263525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED"); 2264525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeActivated = new Intent(); 2265525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED); 2266525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeActivated); 2267525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 2268525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2269525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 2270525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_DEACTIVATED: { 2271525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED"); 2272525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeDeactivated = new Intent(); 2273525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED); 2274525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeDeactivated); 2275525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 2276525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 227731949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 227831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 227931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 228031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 2281b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 2282d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 228314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 228414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 2285c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Resume app switches so the receivers can start activites without delay 2286c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfcDispatcher.resumeAppSwitches(); 2287c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 2288e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized(this) { 2289e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen for (PackageInfo pkg : mInstalledPackages) { 2290e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (pkg != null && pkg.applicationInfo != null) { 2291e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 2292e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen intent.setPackage(pkg.packageName); 2293e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mContext.sendBroadcast(intent); 2294e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 2295c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 2296c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 2297c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 229814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 229914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 2300d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 2301d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 2302d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2303d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 2304d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 2305d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 2306d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 2307d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 2308d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 2309d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 2310d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 231131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 231231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 231331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 2314d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 231577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 2316d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 2317d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2318d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 2319d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 2320d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 2321d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2322d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2323d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 2324d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 2325d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2326d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2327d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 2328d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 2329d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 2330d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 2331d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 2332d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2333d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 2334d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 2335d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 2336d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 2337d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 2338d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 2339d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 234031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 234131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 234231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 2343d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 234477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 2345d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 2346d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2347d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2348d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 2349d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2350d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2351d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2352d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 2353d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2354d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 235531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) { 2356f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 2357f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 2358f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 23593dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams != null) { 236031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen try { 236131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 236231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_END); 236331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 23643dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams.callback != null) { 23653dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen readerParams.callback.onTagDiscovered(tag); 23663dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 23673dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } else { 23683dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Follow normal dispatch below 23693dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } 237031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } catch (RemoteException e) { 237131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen Log.e(TAG, "Reader mode remote has died, falling back."); 23723dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Intentional fall-through 23733dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } catch (Exception e) { 23743dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Catch any other exception 23753dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen Log.e(TAG, "App exception, not dispatching."); 23763dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 237731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 237831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 2379ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly if (!mNfcDispatcher.dispatchTag(tag)) { 2380f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 2381d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 2382d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2383d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 23843fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 23853fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 2386b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 2387b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 2388b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 238949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 2390fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 2391fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 2392fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 2393fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 2394fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 2395fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 2396fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 2397fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 2398161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2399fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 2400fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 2401525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 2402525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2403525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRouting(false); 2404525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 2405525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 2406161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2407fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 24087c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 24097c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 24107c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 24117c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 2412525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() { 24130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 24140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 241531949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 2416525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 2417e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 2418e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 2419e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 2420e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 2421e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2422e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 2423e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 2424e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mNfceeAccessControl.invalidateCache(); 2425e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2426e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 2427e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (dataRemoved) { 2428e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen Uri data = intent.getData(); 2429e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (data == null) return; 2430e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen String packageName = data.getSchemeSpecificPart(); 24317a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 2432e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (NfcService.this) { 2433e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mSePackages.contains(packageName)) { 2434e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen new EnableDisableTask().execute(TASK_EE_WIPE); 2435e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mSePackages.remove(packageName); 2436e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 24377a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 2438bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2439bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2440525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 2441525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project EnableDisableTask eeWipeTask = new EnableDisableTask(); 2442525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.execute(TASK_EE_WIPE); 2443525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2444525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.get(); // blocks until EE wipe is complete 2445525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 2446525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2447525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 2448525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2449525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2450525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2451525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2452525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project }; 2453525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 2454525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2455525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 2456525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onReceive(Context context, Intent intent) { 2457525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project String action = intent.getAction(); 2458525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals( 2459525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2460525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2461525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(); 2462525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON) 2463525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_SCREEN_OFF) 2464525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_USER_PRESENT)) { 2465525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2466525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int screenState = SCREEN_STATE_OFF; 2467525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_SCREEN_OFF)) { 2468525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_OFF; 2469525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 2470525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = mKeyguard.isKeyguardLocked() ? 2471525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED; 2472525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 2473525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_ON_UNLOCKED; 2474525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2475525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 247631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 247731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 247831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 247931949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 248031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 248131949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 248231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 248331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 248431949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 248531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 24861668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 24871668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 248831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 248931949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 249031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 249131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 249231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 24933859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 24943859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.onUserSwitched(); 2495341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 249678976de08ad5d5f9d5fcba28f3ea82350907a782Martijn Coenen mAidCache.invalidateCache(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 24974358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen } 2498f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2499f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2500f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 250131949217328bf2357ff044f0d18677fe588c790cNick Pelly 250231949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 250331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 25047d8987f233985a5ff29226890e11012275d325f5Martijn Coenen return Settings.System.getInt(mContentResolver, 25057d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 250631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 250731949217328bf2357ff044f0d18677fe588c790cNick Pelly 2508fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** for debugging only - no i18n */ 250931949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 251031949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 251131949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 251231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 251331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 251431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 251531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 251631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 251731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 251831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 251931949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 252031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 252131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 252231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 252331949217328bf2357ff044f0d18677fe588c790cNick Pelly 2524fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** For debugging only - no i18n */ 2525fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static String screenStateToString(int screenState) { 2526fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly switch (screenState) { 2527fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_OFF: 2528fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "OFF"; 2529fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_LOCKED: 2530fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_LOCKED"; 2531fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_UNLOCKED: 2532fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_UNLOCKED"; 2533fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly default: 2534fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "UNKNOWN"; 2535fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2536fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2537fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 253831949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 253950effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 254050effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 254150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 254250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 254350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 254450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 254550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 254650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 254731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 254831949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 25490b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 2550fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mScreenState=" + screenStateToString(mScreenState)); 2551fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled); 2552fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled); 255331949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 255431949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 255592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly pw.println("mOpenEe=" + mOpenEe); 255677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 2557341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 2558341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen mAidCache.dump(fd, pw, args); 2559341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen } 2560c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.dump(fd, pw, args); 2561391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 256256f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 2563c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 256431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 256531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 256674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 2567