NfcService.java revision 75f63db568f953e935e62cb3046d167b881979c8
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; 286493859b424f65af79e3e13835f7dfed38495c00Martijn Coenenimport com.android.nfc.cardemulation.RegisteredServicesCache; 294bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.NativeNfcManager; 304bbd47e5507d4c47a4d722216606307e45195a0aMartijn Coenenimport com.android.nfc.dhimpl.NativeNfcSecureElement; 31d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenenimport android.app.ActivityManager; 322f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 33275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 3405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 36a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.content.ComponentName; 3731949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 3913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 4013d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 410e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 42483f3065021c878468ab0921140aa9a2c89b4246Martijn Coenenimport android.content.pm.PackageInfo; 4393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 447d8987f233985a5ff29226890e11012275d325f5Martijn Coenenimport android.content.res.Resources.NotFoundException; 45d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 46d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 502094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 5249d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 53a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.nfc.INfcCardEmulation; 54f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 55f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 56f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 570e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 599d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 60a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.nfc.cardemulation.ApduServiceInfo; 61aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 6281c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 637c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 6450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 6596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenenimport android.os.Build; 66b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 67b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 6849d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 69b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 70533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 714467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 72f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 7313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 743e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenenimport android.os.SystemClock; 75525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.os.UserHandle; 76d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 77f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 7831949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 7957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 8031949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 8131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 823ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 8384e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 84c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamiltonimport java.util.List; 8531949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 863ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 87525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectpublic class NfcService implements DeviceHostListener { 88bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 89bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 90c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 9176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 92fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 93d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 94fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 95c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** Regular NFC permission */ 96bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 97bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 98c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 99c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton /** NFC ADMIN permission - only for system apps */ 100bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 101bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 102bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 10377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 105416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 106416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 107416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 108416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 109416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 110416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1111668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 112a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen static final boolean SE_BROADCASTS_WITH_HCE = true; 113a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 114b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 115b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 116b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 119b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 120c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 121c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1222c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1232c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1242c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 125525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_ACTIVATED = 13; 126525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int MSG_SE_LISTEN_DEACTIVATED = 14; 12757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen static final int MSG_LLCP_LINK_FIRST_PACKET = 15; 128d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_ROUTE_AID = 16; 129d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_UNROUTE_AID = 17; 130d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen static final int MSG_COMMIT_ROUTING = 18; 131b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 13231949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 13331949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 13431949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 13531949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 13631949217328bf2357ff044f0d18677fe588c790cNick Pelly 137fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // Screen state, used by mScreenState 138fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_UNKNOWN = 0; 139fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_OFF = 1; 140fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_LOCKED = 2; 141fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int SCREEN_STATE_ON_UNLOCKED = 3; 142fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 14349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 14449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 14549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 14649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1477efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 148c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // Return values from NfcEe.open() - these are 1:1 mapped 149c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen // to the thrown EE_EXCEPTION_ exceptions in nfc-extras. 150c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_IO = -1; 151c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_ALREADY_OPEN = -2; 152c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_INIT = -3; 153c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_LISTEN_MODE = -4; 154c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_EXT_FIELD = -5; 155c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen static final int EE_ERROR_NFC_DISABLED = -6; 156c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 157fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** minimum screen state that enables NFC polling (discovery) */ 158fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED; 159fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 160525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for NFC controller to initialize before watchdog 161525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off. This time is chosen large, because firmware download 162525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // may be a part of initialization. 163525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int INIT_WATCHDOG_MS = 90000; 164525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 165525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for routing to be applied before watchdog 166525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off 167525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int ROUTING_WATCHDOG_MS = 10000; 168525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1693e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Amount of time to wait before closing the NFCEE connection 1703e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // in a disable/shutdown scenario. 1713e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_OPERATIONS_MS = 5000; 1723e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Polling interval for waiting on NFCEE operations 1733e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen static final int WAIT_FOR_NFCEE_POLL_MS = 100; 1743e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 175d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 176d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 177d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 178d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 179d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 18049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 18149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 18249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 18349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 18449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 18549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 18649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 18749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 18896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_UP = 18996e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_UP"; 19096e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 19196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_DOWN = 19296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_DOWN"; 19396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 1942c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1952c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1962c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1972c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1982c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1992c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 2002c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 2012c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 2022c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 2032c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 2042c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 2052c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 2062c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 207525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_ACTIVATED = 208525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED"; 209525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public static final String ACTION_SE_LISTEN_DEACTIVATED = 210525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED"; 21149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 21249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 21349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 2140bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 21549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 21649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 2170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 218d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 219d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 220d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 2212f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 222fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 223525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // mSePackages holds packages that accessed the SE, but only for the owner user, 224525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // as SE access is not granted for non-owner users. 225fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly HashSet<String> mSePackages = new HashSet<String>(); 226fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 2277d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 228fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 229fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing 230fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling 2319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen boolean mHostRouteEnabled; // current Device Host state of host-based routing 232e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 23331949217328bf2357ff044f0d18677fe588c790cNick Pelly 23431949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 23531949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 23631949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 23731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 2382f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 2392f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 24005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 2414a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 2420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 244525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mRoutingWakeLock; 245525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mEeWakeLock; 246525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 247d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 248d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 249d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 250d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 25177d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2524a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2534a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2544a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 255a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen CardEmulationService mCardEmulationService; 25631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 25731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 25896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen boolean mIsDebugBuild; 2590a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen boolean mIsHceCapable; 260c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfceeAccessControl mNfceeAccessControl; 2612ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 26276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 263fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 264275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 2657d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private HandoverManager mHandoverManager; 2667d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private ContentResolver mContentResolver; 267a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen private RegisteredServicesCache mServiceCache; 2689f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen private HostEmulationManager mHostEmulationManager; 269d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen private AidRoutingManager mAidRoutingManager; 270d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 271d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 272d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 27393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 274c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 27593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 27693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 277c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void enforceNfceeAdminPerm(String pkg) { 278c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (pkg == null) { 279c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException("caller must pass a package name"); 280c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 281c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 282c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) { 283c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH + 284c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton " denies NFCEE access to " + pkg); 285c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 286525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { 287525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project throw new SecurityException("only the owner is allowed to call SE APIs"); 288525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 28993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 29093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 291d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 292d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 293d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 296f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 297f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 298f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 299f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 300f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 301f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 302f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 303d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 304f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 305a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3060a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 3070a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 308f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 309f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 310f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 311f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 312f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 313d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 314f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 315a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3160a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_CARD_EMULATION, aid); 3170a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 318f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 319f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 320f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 3219f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen * Notifies transaction 3229f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen */ 3239f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3249f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationActivated() { 3250a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3260a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyHostEmulationActivated(); 3270a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3289f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3299f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3309f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationData(byte[] data) { 3320a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3330a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyHostEmulationData(data); 3340a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3359f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3369f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3379f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 3389f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationDeactivated() { 3390a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mHostEmulationManager != null) { 3400a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mHostEmulationManager.notifyNostEmulationDeactivated(); 3410a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 3429f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 3439f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 3449f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen /** 345f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 346f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 347f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 348f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 349f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 350f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 351f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 352f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 353f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 354f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 355d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 356f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 357f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 358f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 359f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 36057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen /** 36157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen * Notifies P2P Device detected, first packet received over LLCP link 36257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen */ 36357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 36457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 36557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 36657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 36757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 368d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 369f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 370a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3710a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 3720a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 373f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 374f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 375d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 376f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 377a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3780a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 3790a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 380f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 381f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 382f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 383525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenActivated() { 384a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3850a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null); 3860a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 387525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 388525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 389525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 390525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onSeListenDeactivated() { 391a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 3920a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null); 3930a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 394525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 395525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 396525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 397525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 398442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 399a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4000a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 4010a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 402442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 403442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 404442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 405442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 406a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4070a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 4080a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 409442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 410442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 411442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 412442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 413a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4140a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 4150a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 416442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 417442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 418525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public NfcService(Application nfcApplication) { 4194a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 4204a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 421ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 422a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen mCardEmulationService = new CardEmulationService(); 4234a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 4242f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 4252f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 426d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 427d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 428525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext = nfcApplication; 4297d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mContentResolver = mContext.getContentResolver(); 430525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost = new NativeNfcManager(mContext, this); 43174180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 4327d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager = new HandoverManager(mContext); 4337d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean isNfcProvisioningEnabled = false; 4347d8987f233985a5ff29226890e11012275d325f5Martijn Coenen try { 4357d8987f233985a5ff29226890e11012275d325f5Martijn Coenen isNfcProvisioningEnabled = mContext.getResources().getBoolean( 4367d8987f233985a5ff29226890e11012275d325f5Martijn Coenen R.bool.enable_nfc_provisioning); 4377d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } catch (NotFoundException e) { 4387d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 4397d8987f233985a5ff29226890e11012275d325f5Martijn Coenen 4407d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (isNfcProvisioningEnabled) { 4417d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 4427d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 4437d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else { 4447d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = false; 4457d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 446525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 4477d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(!mInProvisionMode); 4487d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode); 4497d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager, 450525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 45124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 45237058bf7b59def2f9a565ae5b16aae54e80e9e95Sunil Jogi mSecureElement = new NativeNfcSecureElement(mContext); 453eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 4540bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 455525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mNfceeAccessControl = new NfceeAccessControl(mContext); 456c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 457525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 4580e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 459f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 46031949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 4610b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 462f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 46396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); 46496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 465525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 466525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 467525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock = mPowerManager.newWakeLock( 468525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 469525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock = mPowerManager.newWakeLock( 470525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock"); 471275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 472525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 473fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = checkScreenState(); 474533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 475d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 476f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 477525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents for all users 478eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 47965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 48065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 481275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 4823859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen filter.addAction(Intent.ACTION_USER_SWITCHED); 48331949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 484525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 4850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 4860a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen PackageManager pm = mContext.getPackageManager(); 4870a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HCE); 4880a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 4890a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mAidRoutingManager = new AidRoutingManager(); 490a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen mServiceCache = new RegisteredServicesCache(mContext, mAidRoutingManager); 491a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen mHostEmulationManager = new HostEmulationManager(mContext, mServiceCache); 492a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen } 493a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) { 4940a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 4950a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 4960a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 4970a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 4980a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 4990a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 5000a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5010a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter = new IntentFilter(); 5020a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 5030a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 5040a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen ownerFilter.addDataScheme("package"); 5050a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5060a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 5070a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen 5080a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen updatePackageCache(); 5090a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 510e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 51131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51331949217328bf2357ff044f0d18677fe588c790cNick Pelly 514d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 515d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 516d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 517d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 518525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 519525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 520525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 521d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 522d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 523d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 524d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 525d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 526d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 527d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 528d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 529d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 530d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 531d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 532d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 533d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 5357d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String airplaneModeRadios = Settings.System.getString(mContentResolver, 5367d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_RADIOS); 5377d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String toggleableRadios = Settings.System.getString(mContentResolver, 5387d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 53931949217328bf2357ff044f0d18677fe588c790cNick Pelly 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 5417d8987f233985a5ff29226890e11012275d325f5Martijn Coenen airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 5437d8987f233985a5ff29226890e11012275d325f5Martijn Coenen toggleableRadios.contains(Settings.Global.RADIO_NFC); 54431949217328bf2357ff044f0d18677fe588c790cNick Pelly 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly 550e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen void updatePackageCache() { 551525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project PackageManager pm = mContext.getPackageManager(); 552525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER); 553e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (this) { 554e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mInstalledPackages = packages; 555e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 556e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 557e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 558fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int checkScreenState() { 559fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (!mPowerManager.isScreenOn()) { 560fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_OFF; 561fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else if (mKeyguard.isKeyguardLocked()) { 562fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_LOCKED; 563fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } else { 564fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return SCREEN_STATE_ON_UNLOCKED; 565fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 566fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 567fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 568525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int doOpenSecureElementConnection() { 569525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 570525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 571525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doOpenSecureElementConnection(); 572525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 573525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 574525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 575525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 576525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 577525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceive(int handle, byte[] cmd) { 578525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 579525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 580525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceiveNoLock(handle, cmd); 581525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 582525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 583525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 584525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 585525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 586525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] doTransceiveNoLock(int handle, byte[] cmd) { 587525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mSecureElement.doTransceive(handle, cmd); 588525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 589525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 590525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project void doDisconnect(int handle) { 591525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 592525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 593525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mSecureElement.doDisconnect(handle); 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 59931949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 60031949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 60131949217328bf2357ff044f0d18677fe588c790cNick Pelly * 60231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 60331949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 60431949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 60531949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 60631949217328bf2357ff044f0d18677fe588c790cNick Pelly * 60731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 61031949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 61231949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly * 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 61631949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 61731949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 61831949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 61931949217328bf2357ff044f0d18677fe588c790cNick Pelly * 62031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 62331949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 62731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 62831949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 62931949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 63031949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 63131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 63231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 63331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 63431949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 63531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 63631949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 63731949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 63831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 63931949217328bf2357ff044f0d18677fe588c790cNick Pelly 6404467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 6414467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 6424467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 6434467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 6444467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 6454467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 6464467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 6474467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 6484467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 64931949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 65031949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 65131949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 65331949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 65431949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 65631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 6570fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 6581668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 65931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 6601668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 6610fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 66231949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 6630fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 6640fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 6650fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 66631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 66731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 66831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 66931949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 67031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 67131949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 67231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 67331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 67431949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 67531949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 67631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 67731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 678d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 679d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 680d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 68131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 68231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 68331949217328bf2357ff044f0d18677fe588c790cNick Pelly 68431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 68531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 68631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 68731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 68831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 68931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 69031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 69131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 69231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 69331949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 69431949217328bf2357ff044f0d18677fe588c790cNick Pelly 695525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 696525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.start(); 697525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 698525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 699525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 700525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (!mDeviceHost.initialize()) { 701525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Error enabling NFC"); 702525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project updateState(NfcAdapter.STATE_OFF); 703525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return false; 704525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 705525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 706525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 707525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 708525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 709525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.cancel(); 71031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 71131949217328bf2357ff044f0d18677fe588c790cNick Pelly 7120a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 7130a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen // Generate the initial card emulation routing table 714a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen mServiceCache.invalidateCache(ActivityManager.getCurrentUser(), true); 7150a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 716d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 71731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 71831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 7190b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 72031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 72131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 72231949217328bf2357ff044f0d18677fe588c790cNick Pelly 723d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 724d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 72531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 7260c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 727fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 72831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 72931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 73031949217328bf2357ff044f0d18677fe588c790cNick Pelly 73131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 73231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 73331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 73431949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 73531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 73631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 73731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 73831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 73931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 74031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 74131949217328bf2357ff044f0d18677fe588c790cNick Pelly 74231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 74331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 74431949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 74531949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 746525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 74731949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 74831949217328bf2357ff044f0d18677fe588c790cNick Pelly 749953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen if (mIsHceCapable) { 750953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen mAidRoutingManager.onNfccRoutingTableCleared(); 751953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen } 752d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 75377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 75431949217328bf2357ff044f0d18677fe588c790cNick Pelly 7553e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen /* The NFC-EE may still be opened by another process, 7563e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * and a transceive() could still be in progress on 7573e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * another Binder thread. 7583e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * Give it a while to finish existing operations 7593e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen * before we close it. 7603e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen */ 7613e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Long startTime = SystemClock.elapsedRealtime(); 7623e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen do { 7633e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen synchronized (NfcService.this) { 7643e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen if (mOpenEe == null) 7653e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen break; 7663e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 7673e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen try { 7683e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen Thread.sleep(WAIT_FOR_NFCEE_POLL_MS); 7693e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } catch (InterruptedException e) { 7703e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen // Ignore 7713e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } 7723e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen } while (SystemClock.elapsedRealtime() - startTime < WAIT_FOR_NFCEE_OPERATIONS_MS); 7733e38dca2bc7c7629d7159663d597a1e886d85527Martijn Coenen 7744ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen synchronized (NfcService.this) { 7754ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (mOpenEe != null) { 7764ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen try { 7774ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen _nfcEeClose(-1, mOpenEe.binder); 7784ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } catch (IOException e) { } 7794ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 7804ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen } 7814ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen 78231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 78331949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 78431949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 78531949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 78631949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 78731949217328bf2357ff044f0d18677fe588c790cNick Pelly 7880b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 78931949217328bf2357ff044f0d18677fe588c790cNick Pelly 79031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 79131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 79231949217328bf2357ff044f0d18677fe588c790cNick Pelly 79331949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 79431949217328bf2357ff044f0d18677fe588c790cNick Pelly 79531949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 79631949217328bf2357ff044f0d18677fe588c790cNick Pelly 797d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 798d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 79931949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 80031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 80131949217328bf2357ff044f0d18677fe588c790cNick Pelly 80231949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 80331949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 804525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[][]apdus = mDeviceHost.getWipeApdus(); 805525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 806525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (apdus == null) { 807525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.d(TAG, "No wipe APDUs found"); 808525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 809525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 81031949217328bf2357ff044f0d18677fe588c790cNick Pelly 81131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 812525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Hold a wake-lock over the entire wipe procedure 813525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.acquire(); 814525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 815525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable && !enableInternal()) { 816ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 81731949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 819525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 820525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // NFC enabled 821525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = 0; 822525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 823525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "Executing SE wipe"); 824525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project handle = doOpenSecureElementConnection(); 8252b4dc11f4508cdb662a8069cccf9f2273004a4c8Martijn Coenen if (handle < 0) { 826525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Could not open the secure element"); 827525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return; 828525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 829525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // TODO: remove this hack 830525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 831525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Thread.sleep(1000); 832525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 833525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Ignore 834525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 83531949217328bf2357ff044f0d18677fe588c790cNick Pelly 836525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 837525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 838525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (byte[] cmd : apdus) { 839525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project byte[] resp = doTransceiveNoLock(handle, cmd); 840525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (resp == null) { 841525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 842525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 843525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 844525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 845525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 846525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.resetTimeouts(); 847525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 848525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 8492b4dc11f4508cdb662a8069cccf9f2273004a4c8Martijn Coenen if (handle >= 0) { 850525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(handle); 851525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 852525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 853525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 854525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (tempEnable) { 855525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project disableInternal(); 856525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 857ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 858525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 859525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEeWakeLock.release(); 86031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 861525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.i(TAG, "SE wipe done"); 86231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 86331949217328bf2357ff044f0d18677fe588c790cNick Pelly 86431949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 8652a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 86631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 86731949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 86831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 86931949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 87031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 87131949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 87231949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 873525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 87431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 87531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 87631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 87731949217328bf2357ff044f0d18677fe588c790cNick Pelly 87831949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 87931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 88031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 88131949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 88231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 8830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 8840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 885d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 886d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 887d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 888d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 889d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 890d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 891d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 892d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 893d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 894d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 895d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 896d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 897d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 898d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 899d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 900d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 901d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 902d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 903d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 904d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 9050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 9064a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 907fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9080e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 90993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 9100e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 91131949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 9121668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 9131668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 9141668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 9151668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 9161668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 9171668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 9181668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 9191668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 9201668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 921f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 92231949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 92331949217328bf2357ff044f0d18677fe588c790cNick Pelly 92431949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 926f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 927fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 928290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 92993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 9300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 931290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 932290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 933290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 934290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 93531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 93631949217328bf2357ff044f0d18677fe588c790cNick Pelly 93731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 940fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9410b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 94231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 9439993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 94431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 945d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 946d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 947d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9480b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 949d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 950d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 9510b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 95231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 95331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 9540b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 9550b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 95631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 9570b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 95831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 95977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 960d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 961d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 962d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 963d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 964d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 965d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9660b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 967d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 968d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 9690b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 97031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 97131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 9720b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 9730b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 97431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 9750b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 97631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 97777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 978d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 979d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 980d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 981d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 982d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 983d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 9840b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 98524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 98605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 987a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 9880b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 9890b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 9900b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 9910b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 992ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 993a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 994a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 995a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 996a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 997a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 998a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 999a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 1000a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 1001a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 1002a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1003a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1004a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1005a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 1006a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 100724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 100824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 100924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 101024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 101124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 101249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 10130b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 10142094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 10152094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 10162094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 1017c96f982f8c0fa061701143a27395acf3b24dfb54Nick Pelly public void setNdefPushCallback(INdefPushCallback callback) { 1018ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10193859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 1020ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 1021ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 1022ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 10230e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 10240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 10250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 10260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1027fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1028c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) { 1029c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 103049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 10310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 10320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1033fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1034a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public INfcCardEmulation getNfcCardEmulationInterface() { 1035a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return mCardEmulationService; 1036a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1037a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1038a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 103931949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 104031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 104131949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 104231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 104331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 104431949217328bf2357ff044f0d18677fe588c790cNick Pelly 104531949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 104631949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 104731949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 10480e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1049391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 1050391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 1051ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 1052391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly enforceAdminPerm(mContext); 1053ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 1054391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 10550c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 10560c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 10570c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 10580c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen enforceAdminPerm(mContext); 10590c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 10600c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 10610c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 10620c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.disableDiscovery(); 10630c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.enableDiscovery(); 10640c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 1065c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 10660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1067a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen final class CardEmulationService extends INfcCardEmulation.Stub { 1068a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1069a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public boolean isDefaultServiceForCategory(int userId, ComponentName service, 1070a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen String category) throws RemoteException { 1071a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1072a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1073a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1074a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen // TODO perm 1075a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen ApduServiceInfo defaultService = mServiceCache.getDefaultServiceForCategory(userId, 1076a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen category); 1077a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return (defaultService != null && defaultService.getComponent().equals(service)); 1078a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1079a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1080a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1081a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public boolean setDefaultServiceForCategory(int userId, ComponentName service, 1082a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen String category) throws RemoteException { 1083a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1084a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1085a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1086a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1087a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen // TODO perm 1088a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return mServiceCache.setDefaultServiceForCategory(userId, service, category); 1089a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 109075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen 109175f63db568f953e935e62cb3046d167b881979c8Martijn Coenen @Override 109275f63db568f953e935e62cb3046d167b881979c8Martijn Coenen public boolean setDefaultForNextTap(int userId, ComponentName service) 109375f63db568f953e935e62cb3046d167b881979c8Martijn Coenen throws RemoteException { 109475f63db568f953e935e62cb3046d167b881979c8Martijn Coenen if (!mIsHceCapable) { 109575f63db568f953e935e62cb3046d167b881979c8Martijn Coenen return false; 109675f63db568f953e935e62cb3046d167b881979c8Martijn Coenen } 109775f63db568f953e935e62cb3046d167b881979c8Martijn Coenen // TODO perm 109875f63db568f953e935e62cb3046d167b881979c8Martijn Coenen return mServiceCache.setDefaultForNextTap(userId, service); 109975f63db568f953e935e62cb3046d167b881979c8Martijn Coenen } 110075f63db568f953e935e62cb3046d167b881979c8Martijn Coenen 1101a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1102a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public List<ApduServiceInfo> getServices(int userId, String category) 1103a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen throws RemoteException { 1104a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1105a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return null; 1106a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1107a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen // TODO perm 1108a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return mServiceCache.getServicesForCategory(userId, category); 1109a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1110a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 1111a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 1112a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public boolean isDefaultServiceForAid(int userHandle, ComponentName service, String aid) 1113a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen throws RemoteException { 1114a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen if (!mIsHceCapable) { 1115a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1116a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1117a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen // TODO perm 1118a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen return false; 1119a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 1120a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen }; 1121a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 11224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 1123fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1124f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 1125d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1126bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1127f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1128f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 112931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1130f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1131f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1133f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1134f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1135f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1136b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 1137b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 113821545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 1139b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 1140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 1142fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 1144f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1146fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1147ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 1148d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1149bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1150f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1151f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 115231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1154f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1157f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1158b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1159b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 1160f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1161ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 1162cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 1163cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1164cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 1165cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 1166ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 1167ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 1168ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 1169ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 1170ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 1171ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 1172ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1173ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 1174f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1175f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1176fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1177aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 1178aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1179aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1180f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1181aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1182aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 118331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1184aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 1185aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1186aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1187aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 1188f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1189aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 1190aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 1191aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 1192aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 1193aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1194aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1195aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1196aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1197aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1198aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1199aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 1200b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 1201d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1202bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 120431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1209f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1211b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1216fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1217b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 1218f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1219b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1220b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 122131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1222b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1223b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1224b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1225b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 1226f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1227b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1228b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1229b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1230b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1231ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 1232b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1233b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1234fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 1236182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1237182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 1238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 124131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 12422c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 12473ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 12482c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 12492c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1250f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 125170bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1253f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1254fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12559d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 125697c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 1257d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1258bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1260f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 1261f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1262f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 126331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1264f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1265f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1266f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1267f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1270bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 1271bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1272bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1273bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 12749d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 12759d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 1276bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 1277bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 1278bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 1279bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 1280bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 1281bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 1282bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 1283bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1284bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 1285f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1286f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1287f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1288f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1289fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1291d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1292bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1293f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1294f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1295f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 129631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1297f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1298f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1299f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1300f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1301f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1302f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1303f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1304f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1306f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1307f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1309f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1310f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1311f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1312f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1313f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1314f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1315f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1317f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1318fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13193fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1320d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1321bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1322f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1323f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1324f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 132531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1326f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1328f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1329f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1330f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1331f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1332f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1333f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1334f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1335791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1336791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1337f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1339f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1341f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1342f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1343f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1345fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13463fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 13473fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1348f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1349f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1350fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 13513fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 135203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 135303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1354f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 135503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 135603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 135731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 135803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 135903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 136003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 136103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1362f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 136303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 136403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 136503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 136603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1367f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 136803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1369f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 137003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 137103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1373f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 13740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 13750aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 13760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 13770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1378f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 13790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 13800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 138131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 13820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 13830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 13840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 13850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1386f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 13870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 13880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 13890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 13900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 13910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 13920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1393f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 13940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 13950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 13960aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 13970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 13981b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 13993fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 14003fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 14013fb14d0868594c78a777e805545209636814e223Martijn Coenen 1402f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 14033fb14d0868594c78a777e805545209636814e223Martijn Coenen 14043fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 140531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 14063fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 14073fb14d0868594c78a777e805545209636814e223Martijn Coenen } 14083fb14d0868594c78a777e805545209636814e223Martijn Coenen 14093fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1410f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 14113fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 14123fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 14133fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 14143fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 14153fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 14163fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 14173fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 14183fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 14193fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 14203fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 14213fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1422391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 14233fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 14243fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 14254a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 14263fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 14273fb14d0868594c78a777e805545209636814e223Martijn Coenen } 14283fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 14293fb14d0868594c78a777e805545209636814e223Martijn Coenen } 14303fb14d0868594c78a777e805545209636814e223Martijn Coenen 14311b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1432fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 14331b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1434f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1435fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1436fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1437fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1438fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1439fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1440dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1441dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1442dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1443358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1444358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1445358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1446358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1447358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1448358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1449358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1450dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1451dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1452dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1453f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 14541b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1455bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1456bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1457bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1458bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1459bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1460bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1461bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1462bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1463bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1464bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1465ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1466ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1467ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1468ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1469ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1470c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1471f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 147292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly void _nfcEeClose(int callingPid, IBinder binder) throws IOException { 1473dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1474dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1475dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1476dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 14770571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly synchronized (NfcService.this) { 14784ac28aa73f8bc7b501912fb8e96877a7b9a1f4f2Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1479dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1480dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1481dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1482dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1483dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 148492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (callingPid != -1 && callingPid != mOpenEe.pid) { 1485dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1486dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 148792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly if (mOpenEe.binder != binder) { 148892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly throw new SecurityException("Wrong binder handle"); 148992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 1490dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 149192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly binder.unlinkToDeath(mOpenEe, 0); 1492f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1493525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project doDisconnect(mOpenEe.handle); 1494dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1495dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1496fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1497dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1498dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1499dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 15004a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 150149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 150249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 150349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 150449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 150549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1506c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1507c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private Bundle writeEeException(int exceptionType, String message) { 150849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 1509c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putInt("e", exceptionType); 1510c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen p.putString("m", message); 151149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 151249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1514bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1515c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle open(String pkg, IBinder b) throws RemoteException { 1516c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1517bd555ee64250126b60b24814120a2049943920caNick Pelly 151849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 1519c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen int handle = _open(b); 1520c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1521c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(handle, "NFCEE open exception."); 1522c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen } else { 152349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 15240bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 152549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 152649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15270bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1528c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen /** 1529c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * Opens a connection to the secure element. 1530c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * 1531c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * @return A handle with a value >= 0 in case of success, or a 1532c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen * negative value in case of failure. 1533c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen */ 1534c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen private int _open(IBinder b) { 153549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 153631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1537c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_NFC_DISABLED; 153849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15397a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen if (mInProvisionMode) { 15407a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // Deny access to the NFCEE as long as the device is being setup 15417a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen return EE_ERROR_IO; 15427a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen } 15437a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen if (mDeviceHost.enablePN544Quirks() && mP2pLinkManager.isLlcpActive()) { 15447a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // Don't allow PN544-based devices to open the SE while the LLCP 15457a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // link is still up or in a debounce state. This avoids race 15467a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen // conditions in the NXP stack around P2P/SMX switching. 15477a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen return EE_ERROR_EXT_FIELD; 15487a499e775021bafefbe890d079e2a43f4a54482cMartijn Coenen } 154949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 1550c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return EE_ERROR_ALREADY_OPEN; 155149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15520bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1553476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen boolean restorePolling = false; 1554476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen if (mDeviceHost.enablePN544Quirks() && mNfcPollingEnabled) { 1555476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // Disable polling for tags/P2P when connecting to the SMX 1556476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // on PN544-based devices. Whenever nfceeClose is called, 1557476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen // the polling configuration will be restored. 1558476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mDeviceHost.disableDiscovery(); 1559476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mNfcPollingEnabled = false; 1560476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen restorePolling = true; 1561476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen } 1562476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen 1563525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int handle = doOpenSecureElementConnection(); 1564c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen if (handle < 0) { 1565476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen 1566476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen if (restorePolling) { 1567476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mDeviceHost.enableDiscovery(); 1568476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen mNfcPollingEnabled = true; 1569476ee8a64404b7ee042ba1a70400bcb1dd5ace10Martijn Coenen } 1570c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 157149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1572525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000); 1573ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 157492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle, b); 157549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 157649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 157749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 157849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 157949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 158084e1e0adc2516afd35ebab029a52e764e0490559Jason parks 158184e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 158284e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 1583525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) { 158484e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 158584e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 1586c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 1587c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen return handle; 158849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 15890bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 15900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1591bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 159292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public Bundle close(String pkg, IBinder binder) throws RemoteException { 1593c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1594c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 159549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 159649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 159792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(getCallingPid(), binder); 159849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 159949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1600c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 16010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 160249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 160349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16040bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1605bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1606c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public Bundle transceive(String pkg, byte[] in) throws RemoteException { 1607c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1608bd555ee64250126b60b24814120a2049943920caNick Pelly 160949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 161049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 161149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 161249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 161349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 161449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 161549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 1616c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen result = writeEeException(EE_ERROR_IO, e.getMessage()); 16170bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 161849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 161949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16200bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1621c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly private byte[] _transceive(byte[] data) throws IOException { 162249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 162331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 162449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 162549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16260571ce53451baf7d363703b6e3ac10bc885fc5bcNick Pelly if (mOpenEe == null) { 162749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 162849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 162949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 163049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 163149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 16320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 16330bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1634525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return doTransceive(mOpenEe.handle, data); 16350bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 16360bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1637bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1638c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public int getCardEmulationRoute(String pkg) throws RemoteException { 1639c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 164049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 16410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 16420bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1643bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1644c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void setCardEmulationRoute(String pkg, int route) throws RemoteException { 1645c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 164649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 1647525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask(); 1648525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.execute(); 1649525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 1650525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Block until route is set 1651525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRoutingTask.get(); 1652525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 1653525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1654525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 1655525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.e(TAG, "failed to set card emulation mode"); 1656525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 16570bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1658bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1659bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 1660c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton public void authenticate(String pkg, byte[] token) throws RemoteException { 1661c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton NfcService.this.enforceNfceeAdminPerm(pkg); 1662bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1663525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1664525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 1665525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public String getDriverName(String pkg) throws RemoteException { 1666525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NfcService.this.enforceNfceeAdminPerm(pkg); 1667525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return mDeviceHost.getName(); 1668525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1669c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 16700bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 167149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 167249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 167349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 167492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // binder handle used for DeathReceipient. Must keep 167592250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // a reference to this, otherwise it can get GC'd and 167692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // the binder stub code might create a different BinderProxy 167792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // for the same remote IBinder, causing mismatched 167892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly // link()/unlink() 167992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public IBinder binder; 168049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 168192250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public OpenSecureElement(int pid, int handle, IBinder binder) { 168249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 168349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 168492250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly this.binder = binder; 168549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1686bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 168749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 168849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 168992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly Log.i(TAG, "Tracked app " + pid + " died"); 169049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 16910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 169292250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly _nfcEeClose(-1, binder); 1693dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 16940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 16950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 169692250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly @Override 169792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly public String toString() { 169892250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=") 169992250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly .append(pid).append(" handle=").append(handle).append("]").toString(); 170092250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly } 17010bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 17020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 17039a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 17049a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 17059a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 17069a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 17079a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 17089a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 170931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 171031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 171131949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1712e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1713aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1714aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 171531949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 1716a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project final Object mCancelWaiter = new Object(); 1717525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project final int mTimeout; 1718a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project boolean mCanceled = false; 1719525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1720525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public WatchDogThread(String threadName, int timeout) { 1721525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project super(threadName); 1722525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mTimeout = timeout; 1723525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1724525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 17252edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 17262edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 1727a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project try { 1728a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1729a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.wait(mTimeout); 1730a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project if (mCanceled) { 1731a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project return; 1732a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 17332edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1734a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } catch (InterruptedException e) { 1735a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project // Should not happen; fall-through to abort. 1736a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.w(TAG, "Watchdog thread interruped."); 1737a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project interrupt(); 17382edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1739a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.e(TAG, "Watchdog triggered, aborting."); 1740a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mDeviceHost.doAbort(); 17412edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1742a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project 17432edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 1744a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1745a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCanceled = true; 1746a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.notify(); 1747a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 17482edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 17492edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 17502edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 17519f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen static byte[] hexStringToBytes(String s) { 17529f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (s == null || s.length() == 0) return null; 17539f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen int len = s.length(); 17549f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (len % 2 != 0) { 17559f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen s = '0' + s; 17569f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen len++; 17579f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 17589f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen byte[] data = new byte[len / 2]; 17599f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen for (int i = 0; i < len; i += 2) { 17609f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 17619f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen + Character.digit(s.charAt(i+1), 16)); 17629f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 17639f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return data; 17649f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 17659f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1766fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1767fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1768fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1769fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1770e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 17719a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) { 1772fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // PN544 cannot be reconfigured while EE is open 1773e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1774e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1775525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 17767d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (mInProvisionMode) { 17777d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 17787d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 17797d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mInProvisionMode) { 17807d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Notify dispatcher it's fine to dispatch to any package now 17817d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // and allow handover transfers. 17827d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher.disableProvisioningMode(); 17837d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mHandoverManager.setEnabled(true); 17847d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 17857d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1786f439271150e4548f116919e0254d57655421581cMartijn Coenen try { 1787f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.start(); 1788f439271150e4548f116919e0254d57655421581cMartijn Coenen 1789525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) { 1790f439271150e4548f116919e0254d57655421581cMartijn Coenen /* TODO undo this after the LLCP stack is fixed. 1791f439271150e4548f116919e0254d57655421581cMartijn Coenen * Use a different sequence when turning the screen off to 1792f439271150e4548f116919e0254d57655421581cMartijn Coenen * workaround race conditions in pn544 libnfc. The race occurs 1793f439271150e4548f116919e0254d57655421581cMartijn Coenen * when we change routing while there is a P2P target connect. 1794f439271150e4548f116919e0254d57655421581cMartijn Coenen * The async LLCP callback will crash since the routing code 1795f439271150e4548f116919e0254d57655421581cMartijn Coenen * is overwriting globals it relies on. 1796f439271150e4548f116919e0254d57655421581cMartijn Coenen */ 1797f439271150e4548f116919e0254d57655421581cMartijn Coenen if (POLLING_MODE > SCREEN_STATE_OFF) { 1798f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1799f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF, disconnect"); 1800f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1801f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1802f439271150e4548f116919e0254d57655421581cMartijn Coenen maybeDisconnectTarget(); 1803f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1804f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1805f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1806f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1807f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE OFF"); 1808f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = false; 1809f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doDeselectSecureElement(); 1810f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1811fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1812f439271150e4548f116919e0254d57655421581cMartijn Coenen return; 1813fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1814f439271150e4548f116919e0254d57655421581cMartijn Coenen 18150a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable && mScreenState >= SCREEN_STATE_ON_LOCKED && 1816d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mAidRoutingManager.aidsRoutedToHost()) { 1817d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen if (!mHostRouteEnabled || force) { 1818d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHostRouteEnabled = true; 1819d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.enableRoutingToHost(); 1820d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1821d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } else { 1822d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen if (force || mHostRouteEnabled) { 1823d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHostRouteEnabled = false; 1824d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.disableRoutingToHost(); 18259f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18269f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 18279f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1828f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-EE routing 1829f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= SCREEN_STATE_ON_LOCKED && 1830f439271150e4548f116919e0254d57655421581cMartijn Coenen mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1831f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfceeRouteEnabled) { 1832f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-EE ON"); 1833f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfceeRouteEnabled = true; 1834f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.doSelectSecureElement(); 1835f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1836f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1837f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfceeRouteEnabled) { 1838fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly Log.d(TAG, "NFC-EE OFF"); 1839fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mNfceeRouteEnabled = false; 1840fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mDeviceHost.doDeselectSecureElement(); 1841fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1842fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1843fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1844f439271150e4548f116919e0254d57655421581cMartijn Coenen // configure NFC-C polling 1845f439271150e4548f116919e0254d57655421581cMartijn Coenen if (mScreenState >= POLLING_MODE) { 1846f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || !mNfcPollingEnabled) { 1847f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C ON"); 1848f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = true; 1849f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.enableDiscovery(); 1850f439271150e4548f116919e0254d57655421581cMartijn Coenen } 18517d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else if (mInProvisionMode && mScreenState >= SCREEN_STATE_ON_LOCKED) { 18527d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Special case for setup provisioning 18537d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mNfcPollingEnabled) { 18547d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Log.d(TAG, "NFC-C ON"); 18557d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcPollingEnabled = true; 18567d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mDeviceHost.enableDiscovery(); 18577d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 1858f439271150e4548f116919e0254d57655421581cMartijn Coenen } else { 1859f439271150e4548f116919e0254d57655421581cMartijn Coenen if (force || mNfcPollingEnabled) { 1860f439271150e4548f116919e0254d57655421581cMartijn Coenen Log.d(TAG, "NFC-C OFF"); 1861f439271150e4548f116919e0254d57655421581cMartijn Coenen mNfcPollingEnabled = false; 1862f439271150e4548f116919e0254d57655421581cMartijn Coenen mDeviceHost.disableDiscovery(); 1863f439271150e4548f116919e0254d57655421581cMartijn Coenen } 1864fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1865f439271150e4548f116919e0254d57655421581cMartijn Coenen } finally { 1866f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.cancel(); 1867221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 186865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 186965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 187065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 18712436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 187231949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 18739a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1874a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1875a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 187631949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 187731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 187831949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 187931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 188031949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 188131949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 188231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 188331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 188431949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 188531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 188631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 188731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 188831949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 188931949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 189031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 189131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 189231949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 189331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 189431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 189531949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 189631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 189731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 189831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1899bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1900bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1901bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1902bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1903bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 190431949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 190531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 190631949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 190731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 190831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 19092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 191031949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 19110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1912f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1913f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 191431949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 191531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 191631949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1917f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1918b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1919b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 192031949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 192131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 192231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 192331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1924f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1925f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1926d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 19274a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1928c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 19294a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1930d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1931d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1932d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 19333b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1934e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 19353b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1936e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1937e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 1938e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen /** For use by code in this process */ 19394a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1940c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 19414a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1942d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1943d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 194457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1945b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 194657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 194757d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1948d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void routeAids(String aid, int route) { 1949d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen Message msg = mHandler.obtainMessage(); 1950d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.what = MSG_ROUTE_AID; 1951d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.arg1 = route; 1952d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.obj = aid; 1953d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendMessage(msg); 1954d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1955d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1956d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void unrouteAids(String aid) { 1957d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen sendMessage(MSG_UNROUTE_AID, aid); 1958d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1959d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1960d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void commitRouting() { 1961d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING); 1962d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1963d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 19649f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public boolean sendData(byte[] data) { 19659f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return mDeviceHost.sendRawFrame(data); 19669f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 19679f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1968b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1969b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1970b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1971b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1972b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1973b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1974b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 19753fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1976b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1977b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 197831949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 1979d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_ROUTE_AID: { 1980d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen int route = msg.arg1; 1981d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1982d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.routeAid(hexStringToBytes(aid), route); 1983d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen // Restart polling config 1984d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1985d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1986d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_UNROUTE_AID: { 1987d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1988d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.unrouteAid(hexStringToBytes(aid)); 1989d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1990d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1991d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_COMMIT_ROUTING: { 1992d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen applyRouting(true); 1993d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1994d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 199531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 199631949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 199731949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 199831949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 199931949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 200031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 200131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 200231949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 200331949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 200431949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 200531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 200631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 2007ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag); 200831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 2009d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 201077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 2011d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 201231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 201331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 201431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 201557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 201631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 201731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 201831949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 2019d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_START); 202089baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 202189baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // When these tags start containing NDEF, they will require 202289baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // the stack to deal with them in a different way, since 202389baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // they are activated only really shortly. 202489baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // For now, don't consider NDEF on these. 202589baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 202689baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen tag.startPresenceChecking(); 202789baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen dispatchTagEndpoint(tag); 202889baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen break; 202989baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen } 2030391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 2031c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 2032391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 203331949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 2034ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 203531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 203631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 203731949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 2038ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly dispatchTagEndpoint(tag); 203931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 204031949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 2041d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 204231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 204331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 204431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 204531949217328bf2357ff044f0d18677fe588c790cNick Pelly 204631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 204731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 204831949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 204931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 205031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 205131949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 205231949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 205331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 205414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 205531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 205631949217328bf2357ff044f0d18677fe588c790cNick Pelly 205731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 205831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 205931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 206031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 206131949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 206231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 206314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 206431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 206531949217328bf2357ff044f0d18677fe588c790cNick Pelly 206631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 206731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 206831949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 206931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 207031949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 207131949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 207231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 207331949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 207431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 207531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 207614a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 207731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 207831949217328bf2357ff044f0d18677fe588c790cNick Pelly 207931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 208031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 208131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 208231949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 208331949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 208431949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 208531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 208631949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 208731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 208831949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 208931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 209031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 209114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 209231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 2093c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 209431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 209596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 209696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent actIntent = new Intent(ACTION_LLCP_UP); 209796e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(actIntent); 209896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 209931949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 210031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 210131949217328bf2357ff044f0d18677fe588c790cNick Pelly 210231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 210396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 210496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent deactIntent = new Intent(ACTION_LLCP_DOWN); 210596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(deactIntent); 210696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 210731949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 210831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 210931949217328bf2357ff044f0d18677fe588c790cNick Pelly 211031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 211131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 211231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 211331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 211431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 211531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 211631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 211731949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 211831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 211931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 212031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 212131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 212231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 212331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 212431949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 212531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 212631949217328bf2357ff044f0d18677fe588c790cNick Pelly 212777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 212831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 212957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen case MSG_LLCP_LINK_FIRST_PACKET: 213057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mP2pLinkManager.onLlcpFirstPacketReceived(); 213157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen break; 213231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 213331949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 213431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 213531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 213631949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 213731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 213831949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 213931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 214031949217328bf2357ff044f0d18677fe588c790cNick Pelly 214131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 214231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 214331949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 214431949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 214514a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 214631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 214731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 214831949217328bf2357ff044f0d18677fe588c790cNick Pelly 214931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 215031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 215131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 215231949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 215314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 215431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 215531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 215631949217328bf2357ff044f0d18677fe588c790cNick Pelly 2157525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_ACTIVATED: { 2158525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED"); 2159525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeActivated = new Intent(); 2160525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED); 2161525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeActivated); 2162525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 2163525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2164525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 2165525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project case MSG_SE_LISTEN_DEACTIVATED: { 2166525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED"); 2167525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Intent listenModeDeactivated = new Intent(); 2168525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED); 2169525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project sendSeBroadcast(listenModeDeactivated); 2170525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project break; 2171525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 217231949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 217331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 217431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 217531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 2176b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 2177d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 217814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 217914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 2180c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton // Resume app switches so the receivers can start activites without delay 2181c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfcDispatcher.resumeAppSwitches(); 2182c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 2183e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized(this) { 2184e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen for (PackageInfo pkg : mInstalledPackages) { 2185e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (pkg != null && pkg.applicationInfo != null) { 2186e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 2187e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen intent.setPackage(pkg.packageName); 2188e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mContext.sendBroadcast(intent); 2189e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 2190c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 2191c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 2192c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton } 219314a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 219414a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 2195d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 2196d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 2197d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2198d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 2199d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 2200d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 2201d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 2202d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 2203d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 2204d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 2205d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 220631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 220731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 220831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 2209d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 221077d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 2211d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 2212d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2213d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 2214d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 2215d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 2216d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2217d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2218d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 2219d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 2220d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2221d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2222d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 2223d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 2224d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 2225d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 2226d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 2227d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2228d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 2229d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 2230d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 2231d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 2232d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 2233d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 2234d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 223531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 223631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 223731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 2238d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 223977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 2240d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 2241d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2242d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2243d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 2244d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2245d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2246d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2247d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 2248d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 2249d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 2250ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly private void dispatchTagEndpoint(TagEndpoint tagEndpoint) { 2251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 2252f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 2253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 2254ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly if (!mNfcDispatcher.dispatchTag(tag)) { 2255f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 2256d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 2257d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 2258d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 22593fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 22603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 2261b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 2262b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 2263b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 226449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 2265fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 2266fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 2267fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 2268fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 2269fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 2270fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 2271fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 2272fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 2273161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2274fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 2275fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 2276525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 2277525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2278525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRouting(false); 2279525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 2280525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 2281161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 2282fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 22837c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 22847c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 22857c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 22867c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 2287525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() { 22880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 22890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 229031949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 2291525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 2292e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 2293e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 2294e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 2295e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen updatePackageCache(); 2296e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2297e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 2298e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 2299e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mNfceeAccessControl.invalidateCache(); 2300e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen 2301e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 2302e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (dataRemoved) { 2303e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen Uri data = intent.getData(); 2304e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (data == null) return; 2305e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen String packageName = data.getSchemeSpecificPart(); 23067a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 2307e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen synchronized (NfcService.this) { 2308e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen if (mSePackages.contains(packageName)) { 2309e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen new EnableDisableTask().execute(TASK_EE_WIPE); 2310e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen mSePackages.remove(packageName); 2311e288a8c852ad826efcb2ef5a318394974918209dMartijn Coenen } 23127a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 2313bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2314bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 2315525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 2316525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project EnableDisableTask eeWipeTask = new EnableDisableTask(); 2317525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.execute(TASK_EE_WIPE); 2318525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 2319525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project eeWipeTask.get(); // blocks until EE wipe is complete 2320525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (ExecutionException e) { 2321525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2322525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } catch (InterruptedException e) { 2323525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "failed to wipe NFC-EE"); 2324525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2325525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2326525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2327525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project }; 2328525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 2329525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2330525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 2331525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onReceive(Context context, Intent intent) { 2332525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project String action = intent.getAction(); 2333525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals( 2334525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2335525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2336525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(); 2337525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON) 2338525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_SCREEN_OFF) 2339525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_USER_PRESENT)) { 2340525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 2341525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project int screenState = SCREEN_STATE_OFF; 2342525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_SCREEN_OFF)) { 2343525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_OFF; 2344525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 2345525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = mKeyguard.isKeyguardLocked() ? 2346525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED; 2347525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 2348525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project screenState = SCREEN_STATE_ON_UNLOCKED; 2349525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 2350525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 235131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 235231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 235331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 235431949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 235531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 235631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 235731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 235831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 235931949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 236031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 23611668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 23621668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 236331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 236431949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 236531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 236631949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 236731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 23683859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 23693859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen mP2pLinkManager.onUserSwitched(); 2370f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2371f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2372f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 237331949217328bf2357ff044f0d18677fe588c790cNick Pelly 237431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 237531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 23767d8987f233985a5ff29226890e11012275d325f5Martijn Coenen return Settings.System.getInt(mContentResolver, 23777d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 237831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 237931949217328bf2357ff044f0d18677fe588c790cNick Pelly 2380fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** for debugging only - no i18n */ 238131949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 238231949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 238331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 238431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 238531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 238631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 238731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 238831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 238931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 239031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 239131949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 239231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 239331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 239431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 239531949217328bf2357ff044f0d18677fe588c790cNick Pelly 2396fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** For debugging only - no i18n */ 2397fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly static String screenStateToString(int screenState) { 2398fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly switch (screenState) { 2399fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_OFF: 2400fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "OFF"; 2401fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_LOCKED: 2402fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_LOCKED"; 2403fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly case SCREEN_STATE_ON_UNLOCKED: 2404fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "ON_UNLOCKED"; 2405fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly default: 2406fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return "UNKNOWN"; 2407fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2408fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 2409fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 241031949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 241150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 241250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 241350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 241450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 241550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 241650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 241750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 241850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 241931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 242031949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 24210b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 2422fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mScreenState=" + screenStateToString(mScreenState)); 2423fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled); 2424fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled); 242531949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 242631949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 242792250f5cc5e34549985c31a053feff85b21c60c0Nick Pelly pw.println("mOpenEe=" + mOpenEe); 242877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 2429c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton mNfceeAccessControl.dump(fd, pw, args); 2430391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 243156f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 2432c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton 243331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 243431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 243574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 2436