NfcService.java revision b82d80d891077ccd74729e4143925a66eb89eef2
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 19efb7a3df560585994cebd40fcf5ffbc864f8c358Martijn Coenenimport android.app.ActivityManager; 202f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 21275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 2205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 23b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franzimport android.app.admin.DevicePolicyManager; 2413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 25a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenenimport android.content.ComponentName; 2631949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 2713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 2813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 2913d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 31b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franzimport android.content.pm.IPackageManager; 32c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.PackageInfo; 3393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 34b42756d47f39774a07654f68af27bf3cc2c41511Andres Moralesimport android.content.pm.UserInfo; 357d8987f233985a5ff29226890e11012275d325f5Martijn Coenenimport android.content.res.Resources.NotFoundException; 36d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 37d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 389340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenenimport android.nfc.BeamShareData; 39f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 40f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 4131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenenimport android.nfc.IAppCallback; 420e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4349d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 44a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenenimport android.nfc.INfcCardEmulation; 45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 4616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Moralesimport android.nfc.INfcUnlockHandler; 47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 519d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 52aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5381c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 547c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 5550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 5696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenenimport android.os.Build; 57b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 58b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 5949d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 60b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 61533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 624467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 63f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 6413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 65525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectimport android.os.UserHandle; 665c452dad7b24f28223414ce5e953bfcab782570eAndres Moralesimport android.os.UserManager; 67d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 68f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 704309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.DeviceHostListener; 714309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.LlcpConnectionlessSocket; 724309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.LlcpServerSocket; 734309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.LlcpSocket; 744309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.NfcDepEndpoint; 754309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.DeviceHost.TagEndpoint; 76af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenenimport com.android.nfc.cardemulation.CardEmulationManager; 774309f9c7c0097bdd95cf791eef78700b106dec21Andres Moralesimport com.android.nfc.dhimpl.NativeNfcManager; 78b82d80d891077ccd74729e4143925a66eb89eef2Andres Moralesimport com.android.nfc.handover.HandoverDataParser; 794309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales 8031949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 8131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 8231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 833ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 84c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.util.List; 8528a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Moralesimport java.util.Map; 86c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenenimport java.util.NoSuchElementException; 873ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 88525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectpublic class NfcService implements DeviceHostListener { 89c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 9076a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 91fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 92d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 93fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 9477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 95f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 96416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 97416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 98416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 99416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 100416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 101416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1021668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 103a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 104b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 105c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_ACTIVATION = 1; 106c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_DEACTIVATED = 2; 107c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_MOCK_NDEF = 3; 108c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_FIRST_PACKET = 4; 109c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_ROUTE_AID = 5; 110c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_UNROUTE_AID = 6; 111c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_COMMIT_ROUTING = 7; 112c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_INVOKE_BEAM = 8; 113c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_RF_FIELD_ACTIVATED = 9; 114c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_RF_FIELD_DEACTIVATED = 10; 115e276d3323d755d8bdaccd59a551332c064970215Andres Morales static final int MSG_RESUME_POLLING = 11; 11642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 11742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales static final long MAX_POLLING_PAUSE_TIMEOUT = 40000; 118b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 11931949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 12031949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 12131949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 122c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 123a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales // Polling technology masks 124a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_A = 0x01; 125a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_B = 0x02; 126a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_F = 0x04; 127a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_ISO15693 = 0x08; 128a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_B_PRIME = 0x10; 129a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_KOVIO = 0x20; 130fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1310799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // minimum screen state that enables NFC polling 1320799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1330799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 134525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for NFC controller to initialize before watchdog 135525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off. This time is chosen large, because firmware download 136525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // may be a part of initialization. 137525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int INIT_WATCHDOG_MS = 90000; 138525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 139525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for routing to be applied before watchdog 140525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off 141525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int ROUTING_WATCHDOG_MS = 10000; 142525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 14331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen // Default delay used for presence checks 14431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen static final int DEFAULT_PRESENCE_CHECK_DELAY = 125; 14531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 14634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // The amount of time we wait before manually launching 14734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // the Beam animation when called through the share menu. 14834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen static final int INVOKE_BEAM_DELAY_MS = 1000; 14934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen 150c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // RF field events as defined in NFC extras 151c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public static final String ACTION_RF_FIELD_ON_DETECTED = 152c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 153c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public static final String ACTION_RF_FIELD_OFF_DETECTED = 154c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 155c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 156d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 157d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 158d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 159d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 160d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 16196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_UP = 16296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_UP"; 16396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 16496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_DOWN = 16596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_DOWN"; 16696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 16742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales // Timeout to re-apply routing if a tag was present and we postponed it 16842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales private static final int APPLY_ROUTING_RETRY_TIMEOUT_MS = 5000; 16942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 1705c452dad7b24f28223414ce5e953bfcab782570eAndres Morales private final UserManager mUserManager; 1715c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 17249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 17349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 174c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen private final ReaderModeDeathRecipient mReaderModeDeathRecipient = 175c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen new ReaderModeDeathRecipient(); 17616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales private final NfcUnlockManager mNfcUnlockManager; 1770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 178c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private final NfceeAccessControl mNfceeAccessControl; 179c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 180c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 181c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1822f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 183fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 184fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 1857d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 186fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 187ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen NfcDiscoveryParameters mCurrentDiscoveryParameters = 188ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen NfcDiscoveryParameters.getNfcOffParameters(); 18928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 19031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams mReaderModeParams; 19131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 19231949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 19331949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 19431949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 19531949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 19705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 1984a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 1990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 201525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mRoutingWakeLock; 202525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 203d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 204d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 205d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 206d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 20777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2084a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2094a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 21031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 21131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 21296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen boolean mIsDebugBuild; 2130a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen boolean mIsHceCapable; 21442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales boolean mPollingPaused; 2152ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 21676a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 217fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 218275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 219b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales private HandoverDataParser mHandoverDataParser; 2207d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private ContentResolver mContentResolver; 221af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen private CardEmulationManager mCardEmulationManager; 22228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 2234309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales private ScreenStateHelper mScreenStateHelper; 22434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen private ForegroundUtils mForegroundUtils; 225d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 22628a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales private int mUserId; 2274309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales private static NfcService sService; 22889c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen 229d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 230d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 231d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2330e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 234f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 235f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 236f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 237f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 239f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 241d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 2429f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationActivated() { 243af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 244af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationActivated(); 2450a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2469f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2479f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2489f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 2499f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationData(byte[] data) { 250af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 251af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationData(data); 2520a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2539f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2549f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2559f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 2569f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationDeactivated() { 257af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 258af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationDeactivated(); 2590a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2609f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2619f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2629f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen /** 263f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 271f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 273d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 274f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 275f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 277f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 27857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen /** 27957a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen * Notifies P2P Device detected, first packet received over LLCP link 28057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen */ 28157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 28257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 28357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 28457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 28557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 286c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen @Override 287c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onRemoteFieldActivated() { 288c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendMessage(NfcService.MSG_RF_FIELD_ACTIVATED, null); 289c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 290c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 291c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onRemoteFieldDeactivated() { 292c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendMessage(NfcService.MSG_RF_FIELD_DEACTIVATED, null); 293c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 294c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 29531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen final class ReaderModeParams { 29631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int flags; 29731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public IAppCallback callback; 29831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int presenceCheckDelay; 29931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 30031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 301525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public NfcService(Application nfcApplication) { 302d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mUserId = ActivityManager.getCurrentUser(); 3034309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mContext = nfcApplication; 3044309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales 3054a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 3064a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 3072f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 3082f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 309d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 310d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 3114309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mScreenStateHelper = new ScreenStateHelper(mContext); 3127d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mContentResolver = mContext.getContentResolver(); 313525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost = new NativeNfcManager(mContext, this); 31474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 31516ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales mNfcUnlockManager = NfcUnlockManager.getInstance(); 31616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 317b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mHandoverDataParser = new HandoverDataParser(); 3187d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean isNfcProvisioningEnabled = false; 3197d8987f233985a5ff29226890e11012275d325f5Martijn Coenen try { 3207d8987f233985a5ff29226890e11012275d325f5Martijn Coenen isNfcProvisioningEnabled = mContext.getResources().getBoolean( 3217d8987f233985a5ff29226890e11012275d325f5Martijn Coenen R.bool.enable_nfc_provisioning); 3227d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } catch (NotFoundException e) { 3237d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 3247d8987f233985a5ff29226890e11012275d325f5Martijn Coenen 3257d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (isNfcProvisioningEnabled) { 3267d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 3277d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 3287d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else { 3297d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = false; 3307d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 331525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 332b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode); 333b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser, 334525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 33524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 336525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 3370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 338f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 339c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccessControl = new NfceeAccessControl(mContext); 340c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 34131949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3420b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 343a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(mIsNdefPushEnabled); 344f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 34596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); 34696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 347525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 348525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 349525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock = mPowerManager.newWakeLock( 3504309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 351275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 352525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 3535c452dad7b24f28223414ce5e953bfcab782570eAndres Morales mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 3545c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 3554309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mScreenState = mScreenStateHelper.checkScreenState(); 356533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 357d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 358f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 359525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents for all users 360c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); 36165945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 362275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 3633859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen filter.addAction(Intent.ACTION_USER_SWITCHED); 36431949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 365525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 3660e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 367c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 368c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 369c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 370c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 371c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter = new IntentFilter(); 372c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 373c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 374c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addDataScheme("package"); 375c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 376c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 377b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 378b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null); 379b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz 380c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen updatePackageCache(); 381c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 3820a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen PackageManager pm = mContext.getPackageManager(); 383341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION); 3840a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 385af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager = new CardEmulationManager(mContext); 386a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen } 38734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen mForegroundUtils = ForegroundUtils.getInstance(); 38831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 38931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly 391d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 3924309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (this) { 393d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 394d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 395525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 396525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 397525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 398d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 399d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 400d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 401d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 402d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 4034309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (this) { 404d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 405d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 406d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 407d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 408d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 409d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 410d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 41131949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 4127d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String airplaneModeRadios = Settings.System.getString(mContentResolver, 4137d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_RADIOS); 4147d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String toggleableRadios = Settings.System.getString(mContentResolver, 4157d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 41631949217328bf2357ff044f0d18677fe588c790cNick Pelly 41731949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 4187d8987f233985a5ff29226890e11012275d325f5Martijn Coenen airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 41931949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 4204309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales toggleableRadios.contains(Settings.Global.RADIO_NFC); 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly 42231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly 427c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen void updatePackageCache() { 428c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen PackageManager pm = mContext.getPackageManager(); 429c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER); 430c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 431c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mInstalledPackages = packages; 432c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 433c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 434c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 43531949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 43631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 4374309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 43831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 43931949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 44031949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 4424309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 44331949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 44431949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 44531949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 44631949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 44731949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 44831949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 4494309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 45031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 45131949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 4554309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 45731949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 46031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 46131949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 46231949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 46331949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 46531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 46631949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 46731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly 4744467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4754467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4764467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4774467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4784467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4794467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4804467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4814467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4824467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 48331949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 48431949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 48531949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 4914309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "checking on firmware download"); 4921668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 49331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 4941668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 4954309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "NFC is on. Doing normal stuff"); 49631949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 4970fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 4984309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "NFC is off. Checking firmware version"); 4990fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 50031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 50431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 508d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 509d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 510d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 51131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51331949217328bf2357ff044f0d18677fe588c790cNick Pelly 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 51531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 52131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 52331949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly 525525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 526525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.start(); 527525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 528525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 529525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 530304a6342ee7e5620d3b50d988755c035f1686dc2Martijn Coenen if (!mDeviceHost.initialize()) { 531525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Error enabling NFC"); 532525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project updateState(NfcAdapter.STATE_OFF); 533525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return false; 534525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 535525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 536525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 537525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 538525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 539525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.cancel(); 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54131949217328bf2357ff044f0d18677fe588c790cNick Pelly 5420a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 5430a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen // Generate the initial card emulation routing table 544af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onNfcEnabled(); 5450a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 546d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 5474309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 5490b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 55131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly 553d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 554d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 55531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 5560c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 557fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 56531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly 57231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 57331949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 57431949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 576525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 57831949217328bf2357ff044f0d18677fe588c790cNick Pelly 579953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen if (mIsHceCapable) { 580af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onNfcDisabled(); 581953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen } 582d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 58377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 58431949217328bf2357ff044f0d18677fe588c790cNick Pelly 58531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 58631949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 58731949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 58831949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 58931949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 59031949217328bf2357ff044f0d18677fe588c790cNick Pelly 5910b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 59231949217328bf2357ff044f0d18677fe588c790cNick Pelly 593ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen 59431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 59531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 59631949217328bf2357ff044f0d18677fe588c790cNick Pelly 59731949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 59831949217328bf2357ff044f0d18677fe588c790cNick Pelly 599ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen synchronized (NfcService.this) { 600ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen mCurrentDiscoveryParameters = NfcDiscoveryParameters.getNfcOffParameters(); 601ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen updateState(NfcAdapter.STATE_OFF); 602ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen } 60331949217328bf2357ff044f0d18677fe588c790cNick Pelly 604d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 605d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 60631949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 60731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 6102a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 61231949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 61631949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 61731949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 618525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 61931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly 62331949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 62731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6280e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6290e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 630d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 631d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 632d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 633d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 634d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 635d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 636d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 637d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 638d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 639d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 640d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 641d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 642d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 643d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 644d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 645d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 646d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 647d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 648d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 649d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 650d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales synchronized int getUserId() { 651d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales return mUserId; 652d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales } 653d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales 654a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen void setBeamShareActivityState(boolean enabled) { 655b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 656b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // Propagate the state change to all user profiles related to the current 657b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // user. Note that the list returned by getUserProfiles contains the 658b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // current user. 659b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz List <UserHandle> luh = um.getUserProfiles(); 660b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz for (UserHandle uh : luh){ 661b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz enforceBeamShareActivityPolicy(mContext, uh, enabled); 662b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 663b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 664b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz 665b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz void enforceBeamShareActivityPolicy(Context context, UserHandle uh, 666b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz boolean isGlobalEnabled){ 667b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 668b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 669b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz boolean isActiveForUser = 670b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) && 671b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz isGlobalEnabled; 672b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz if (DBG){ 673b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz Log.d(TAG, "Enforcing a policy change on user: " + uh + 674b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz ", isActiveForUser = " + isActiveForUser); 675b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 676b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz try { 677b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz mIpm.setComponentEnabledSetting(new ComponentName( 678b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz BeamShareActivity.class.getPackageName$(), 679b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz BeamShareActivity.class.getName()), 680b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz isActiveForUser ? 681b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 682b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 683b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.DONT_KILL_APP, 684b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz uh.getIdentifier()); 685b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } catch (RemoteException e) { 686b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz Log.w(TAG, "Unable to change Beam status for user " + uh); 687b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 688a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen } 6890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6904a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 691fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 6934309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 69531949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 6961668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 6971668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 6981668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 6991668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 7001668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 7011668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 7021668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 7031668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 7041668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 70631949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 70731949217328bf2357ff044f0d18677fe588c790cNick Pelly 70831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 709f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 710f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 711fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 712290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 7134309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7140e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 715290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 716290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 717290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 718290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 71931949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 72031949217328bf2357ff044f0d18677fe588c790cNick Pelly 72131949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 722f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 723f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 724dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen @Override 72542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales public void pausePolling(int timeoutInMs) { 72642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 72742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 72842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales if (timeoutInMs <= 0 || timeoutInMs > MAX_POLLING_PAUSE_TIMEOUT) { 72942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales Log.e(TAG, "Refusing to pause polling for " + timeoutInMs + "ms."); 73042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales return; 73142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 73242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 73342c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales synchronized (NfcService.this) { 73442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mPollingPaused = true; 73542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mDeviceHost.disableDiscovery(); 73642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.sendMessageDelayed( 73742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.obtainMessage(MSG_RESUME_POLLING), timeoutInMs); 73842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 73942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 74042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 741dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen @Override 74242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales public void resumePolling() { 74342c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 74442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 74542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales synchronized (NfcService.this) { 74642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales if (!mPollingPaused) { 74742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales return; 74842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 74942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 75042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.removeMessages(MSG_RESUME_POLLING); 75142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mPollingPaused = false; 75242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales new ApplyRoutingTask().execute(); 75342c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 75442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 75542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 756fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 7570b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 75831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 7599993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 76031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 761d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 762d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 763d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7640b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 7654309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7664309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 7670b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 76831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 76931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7700b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 7710b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 77231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7730b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 774a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(true); 77531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 77677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 777d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 778d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 779d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 780d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 781d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 782d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7830b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 7844309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7854309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 7860b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 78731949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 78831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7890b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 7900b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 79131949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7920b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 793a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(false); 79431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 79577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 796d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 797d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 798d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 799d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 800d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 801d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 8020b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 80324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 8044309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 805a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 8060b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 8070b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 8080b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 8090b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 810ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 811a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 812a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 813a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 814a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 815a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 816a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 817a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 818a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 819a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 820a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 821a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 822a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 823a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 824a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 82524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 82624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 82724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 82824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 82924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 83049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 8310b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 8322094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 8332094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 8349340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8352094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 83631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setAppCallback(IAppCallback callback) { 8374309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 8385c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 839b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales // don't allow Beam for managed profiles, or devices with a device owner or policy owner 840b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId()); 84165860bb589c5802ffadb14540670408d6c8dfaa9Benjamin Franz if(!mUserManager.hasUserRestriction( 842b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle())) { 8435c452dad7b24f28223414ce5e953bfcab782570eAndres Morales mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 844b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales } else if (DBG) { 845b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales Log.d(TAG, "Disabling default Beam behavior"); 8465c452dad7b24f28223414ce5e953bfcab782570eAndres Morales } 847ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 848ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 849ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 8509340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void invokeBeam() { 8519340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen NfcPermissions.enforceUserPermissions(mContext); 8529340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 85334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen if (mForegroundUtils.isInForeground(Binder.getCallingUid())) { 8549340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mP2pLinkManager.onManualBeamInvoke(null); 8559340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 8569340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen Log.e(TAG, "Calling activity not in foreground."); 8579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8599340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8609340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 86134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen public void invokeBeamInternal(BeamShareData shareData) { 86234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen NfcPermissions.enforceAdminPermissions(mContext); 86334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen Message msg = Message.obtain(); 86434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen msg.what = MSG_INVOKE_BEAM; 86534322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen msg.obj = shareData; 86634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // We have to send this message delayed for two reasons: 86734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 1) This is an IPC call from BeamShareActivity, which is 86834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // running when the user has invoked Beam through the 86934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // share menu. As soon as BeamShareActivity closes, the UI 87034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // will need some time to rebuild the original Activity. 87134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Waiting here for a while gives a better chance of the UI 87234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // having been rebuilt, which means the screenshot that the 87334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Beam animation is using will be more accurate. 87434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 2) Similarly, because the Activity that launched BeamShareActivity 87534322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // with an ACTION_SEND intent is now in paused state, the NDEF 87634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // callbacks that it has registered may no longer be valid. 87734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Allowing the original Activity to resume will make sure we 87834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // it has a chance to re-register the NDEF message / callback, 87934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // so we share the right data. 88034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 88134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Note that this is somewhat of a hack because the delay may not actually 88234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // be long enough for 2) on very slow devices, but there's no better 88334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // way to do this right now without additional framework changes. 88434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS); 88534322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen } 88634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen 88734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen @Override 8880e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 8890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 8900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 8910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 892fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 893a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public INfcCardEmulation getNfcCardEmulationInterface() { 89435b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen if (mIsHceCapable) { 89535b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen return mCardEmulationManager.getNfcCardEmulationInterface(); 89635b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen } else { 89735b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen return null; 89835b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen } 899a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 900a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 901a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 90231949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 90331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 90431949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 90531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 90631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 90731949217328bf2357ff044f0d18677fe588c790cNick Pelly 90831949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 90931949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 91031949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 9110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 912391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 913391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 914ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 9154309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 916ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 917391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 9180c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 9190c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 9200c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 9214309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 9220c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 9230c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 9240799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales applyRouting(true); 9250c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 926c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 927c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 92831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras) 92931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen throws RemoteException { 930c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 931c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen if (flags != 0) { 932c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 93331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = new ReaderModeParams(); 93431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.callback = callback; 93531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.flags = flags; 9364309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mReaderModeParams.presenceCheckDelay = extras != null 9374309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 9384309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales DEFAULT_PRESENCE_CHECK_DELAY)) 9394309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales : DEFAULT_PRESENCE_CHECK_DELAY; 940c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.linkToDeath(mReaderModeDeathRecipient, 0); 941c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (RemoteException e) { 942c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Remote binder has already died."); 943c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen return; 944c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 945c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } else { 946c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 94731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 948c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.unlinkToDeath(mReaderModeDeathRecipient, 0); 949c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (NoSuchElementException e) { 950c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Reader mode Binder was never registered."); 951c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 952c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 953c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 954c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 955c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 956c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen 957c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen @Override 958c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) throws RemoteException { 959c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen // nfc-extras implementation is no longer present in AOSP. 960c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen return null; 961c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen } 96228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 96328a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales @Override 96416ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales public void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, int[] techList) { 96516ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 96616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 96716ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales int lockscreenPollMask = computeLockscreenPollMask(techList); 96816ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales synchronized (NfcService.this) { 96916ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales mNfcUnlockManager.addUnlockHandler(unlockHandler, lockscreenPollMask); 97016ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 97116ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 97216ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales applyRouting(false); 97316ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 97416ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 97516ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales @Override 976af05d4f78bca45a13f54444a67c1da09bdd599a3Andres Morales public void removeNfcUnlockHandler(INfcUnlockHandler token) throws RemoteException { 97716ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales synchronized (NfcService.this) { 978af05d4f78bca45a13f54444a67c1da09bdd599a3Andres Morales mNfcUnlockManager.removeUnlockHandler(token.asBinder()); 97916ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 98016ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 98116ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales applyRouting(false); 98216ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 98316ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 98428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales private int computeLockscreenPollMask(int[] techList) { 98528a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 98628a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>(); 98728a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 98828a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A); 98928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_B, 99028a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales NfcService.NFC_POLL_B | NfcService.NFC_POLL_B_PRIME); 99128a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693); 99228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F); 99328a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO); 99428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 99528a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales int mask = 0; 99628a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 99728a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales for (int i = 0; i < techList.length; i++) { 99828a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales if (techCodeToMask.containsKey(techList[i])) { 99928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales mask |= techCodeToMask.get(techList[i]).intValue(); 100028a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 100128a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 100228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 100328a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales return mask; 100428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 1005c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1006c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 1007c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen final class ReaderModeDeathRecipient implements IBinder.DeathRecipient { 1008c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 1009c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen public void binderDied() { 1010c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 101131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (mReaderModeParams != null) { 101231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 1013c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 1014c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1015c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1016c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1017c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 10180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 10194a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 1020fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1021f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 10224309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1023bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1024f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 102631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1029f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1031f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1033b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 1034b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 103521545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 1036b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 1039fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1040f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 1041f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1042f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1043fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1044ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 10454309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1046bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1047f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 104931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1050f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1051f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1052f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1053f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1054f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1055b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1056b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 1057f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1058ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 1059cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 1060cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1061cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 1062cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 1063ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 1064ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 1065ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 1066ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 1067ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 1068ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 1069ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1070ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 1071f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1072f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1073fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1074aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 10754309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1076aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1077f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1078aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1079aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 108031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1081aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 1082aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1083aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1084aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 1085f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1086aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 1087aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 1088aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 1089aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 1090aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1091aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1092aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1093aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1094aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1095aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1096aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 1097b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 10984309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1099bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1100f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 110131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1102f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1103f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1105f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1106f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1107f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1108b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 1109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1110f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1111f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1112f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1113fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1114b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 1115f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1116b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1117b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 111831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1119b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1120b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1121b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1122b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 1123f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1124b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1125b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1126b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1127b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1128ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 1129b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1130b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1131fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1132f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 11334309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1134182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 1135f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1136f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1137f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 113831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 11392c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1140f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1141f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1143f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 11443ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 11452c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 11462c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 114870bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 1149f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1150f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1151fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11529d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 115397c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 11544309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1155bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1156f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1157f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 1158f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1159f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 116031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1161f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1162f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1165f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1166f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1167bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 1168bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1169bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1170bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 11719d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 11729d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 1173bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 1174bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 1175bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 1176bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 1177bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 1178bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 1179bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 1180bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1181bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 1182f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1183f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1184f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1185f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1186fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11873fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 11884309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1189bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1190f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1192f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 119331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1194f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1195f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1196f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1198f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1199f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1200f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1201f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1203f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1204f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1206f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1207f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1209f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1215fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12163fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 12174309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1218bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1219f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1221f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 122231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1223f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1224f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1227f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1228f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1232791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1233791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1234f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1236f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1238f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1239f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1240f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1242fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 12443fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1247fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12483fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 12494309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 125003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 125203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 125303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 125431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 125503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 125603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 125703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 125803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 126003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 126103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 126203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 126303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 126503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 126703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 126803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1269f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1270f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 12710aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 12720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 12734309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 12740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1275f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 12760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 127831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 12790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 12800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12810aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1283f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 12840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 12850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 12890aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1290f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 12910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12951b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 12963fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 12974309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 12983fb14d0868594c78a777e805545209636814e223Martijn Coenen 1299f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 13003fb14d0868594c78a777e805545209636814e223Martijn Coenen 13013fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 130231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 13033fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 13043fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13053fb14d0868594c78a777e805545209636814e223Martijn Coenen 13063fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1307f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 13083fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 13093fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 13103fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 13113fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 13123fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 13133fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 13143fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 13153fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 13163fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 13173fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 13183fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1319391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 13203fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 13213fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 13224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 13233fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 13243fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13253fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 13263fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13273fb14d0868594c78a777e805545209636814e223Martijn Coenen 13281b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1329fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 13304309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1331f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1332fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1333fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1334fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1335fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1336fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1337dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1338dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1339dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1340358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 13414309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1342358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1343358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1344358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1345358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1346358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1347dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 13484309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1349dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1350f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 13511b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1352bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1353bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1354bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1355bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1356bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1357bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1358bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1359bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1360bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1361bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1362ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1363ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1364ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1365ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1366ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1367c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1368f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 13699a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 13709a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 13719a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 13729a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13739a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13749a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 137531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 137631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 137731949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1378e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1379aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1380aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 138131949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 1382a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project final Object mCancelWaiter = new Object(); 1383525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project final int mTimeout; 1384a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project boolean mCanceled = false; 1385525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1386525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public WatchDogThread(String threadName, int timeout) { 1387525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project super(threadName); 1388525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mTimeout = timeout; 1389525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1390525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 13912edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 13922edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 1393a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project try { 1394a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1395a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.wait(mTimeout); 1396a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project if (mCanceled) { 1397a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project return; 1398a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 13992edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1400a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } catch (InterruptedException e) { 1401a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project // Should not happen; fall-through to abort. 1402a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.w(TAG, "Watchdog thread interruped."); 1403a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project interrupt(); 14042edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1405a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.e(TAG, "Watchdog triggered, aborting."); 1406a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mDeviceHost.doAbort(); 14072edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1408a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project 14092edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 1410a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1411a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCanceled = true; 1412a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.notify(); 1413a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 14142edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 14152edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 14162edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 14179f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen static byte[] hexStringToBytes(String s) { 14189f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (s == null || s.length() == 0) return null; 14199f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen int len = s.length(); 14209f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (len % 2 != 0) { 14219f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen s = '0' + s; 14229f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen len++; 14239f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14249f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen byte[] data = new byte[len / 2]; 14259f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen for (int i = 0; i < len; i += 2) { 14269f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 14274309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales + Character.digit(s.charAt(i + 1), 16)); 14289f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14299f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return data; 14309f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1432fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1433fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1434fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1435fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1436e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 1437c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1438e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1439e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1440525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 14417d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (mInProvisionMode) { 14427d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 14437d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 14447d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mInProvisionMode) { 14457d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Notify dispatcher it's fine to dispatch to any package now 14467d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // and allow handover transfers. 14477d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher.disableProvisioningMode(); 14487d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 14497d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 14500799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Special case: if we're transitioning to unlocked state while 14510799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // still talking to a tag, postpone re-configuration. 14520799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) { 14530799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.d(TAG, "Not updating discovery parameters, tag connected."); 145442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING), 145542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales APPLY_ROUTING_RETRY_TIMEOUT_MS); 14560799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales return; 14570799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 14580799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 1459f439271150e4548f116919e0254d57655421581cMartijn Coenen try { 1460f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.start(); 14610799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Compute new polling parameters 14620799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState); 14630799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (force || !newParams.equals(mCurrentDiscoveryParameters)) { 14640799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (newParams.shouldEnableDiscovery()) { 1465ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery(); 14660799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales mDeviceHost.enableDiscovery(newParams, shouldRestart); 14670799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 1468a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales mDeviceHost.disableDiscovery(); 1469a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales } 14700799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales mCurrentDiscoveryParameters = newParams; 14710799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 14720799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.d(TAG, "Discovery configuration equal, not updating."); 1473fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1474a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales } finally { 1475a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales watchDog.cancel(); 1476221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 147765945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 147865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 147965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 14800799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) { 14810799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Recompute discovery parameters based on screen state 14820799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder(); 14830799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Polling 14840799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (screenState >= NFC_POLLING_MODE) { 14850799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Check if reader-mode is enabled 14860799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mReaderModeParams != null) { 14870799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales int techMask = 0; 14880799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0) 14890799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_A; 14900799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0) 14910799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_B; 14920799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0) 14930799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_F; 14940799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0) 14950799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_ISO15693; 14960799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0) 14970799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_KOVIO; 14980799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 14990799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(techMask); 15000799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableReaderMode(true); 15010799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 15020799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 15030799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 15040799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) { 15050799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 15060799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && 1507731fd8a52cec0dbe8d6ec6a4c7aa36ff52812112Andres Morales mNfcUnlockManager.isLockscreenPollingEnabled()) { 15080799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // For lock-screen tags, no low-power polling 1509731fd8a52cec0dbe8d6ec6a4c7aa36ff52812112Andres Morales paramsBuilder.setTechMask(mNfcUnlockManager.getLockscreenPollMask()); 15100799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableLowPowerDiscovery(false); 1511a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1512a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales 15130799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) { 15140799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Host routing is always enabled at lock screen or later 15150799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableHostRouting(true); 15160799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 15170799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales return paramsBuilder.build(); 1518a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1519a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales 1520a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales private boolean isTagPresent() { 1521a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales for (Object object : mObjectMap.values()) { 1522a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales if (object instanceof TagEndpoint) { 1523a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales return ((TagEndpoint) object).isPresent(); 1524a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1525a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1526a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales return false; 1527a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 15284309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 15294309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * Disconnect any target if present 15304309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 153131949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 15329a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1533a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1534a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 153531949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 153631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 153731949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 153831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 153931949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 154031949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 154131949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 154231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 154331949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 154431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 154531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 154731949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 154831949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 154931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 155231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 155731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1558bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1559bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1560bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1561bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1562bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 156431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 156531949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 156631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 156731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 15682f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 156931949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 15700e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1571f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1572f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 157331949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 157431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 157531949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1576f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1577b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1578b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 157931949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 158031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 158131949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 158231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1584f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 15854309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 15864309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 15874309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 15884a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1589c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 15904a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1591d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1592d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 15934309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 15944309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 15954309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 15963b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1597e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 15983b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1599e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1600e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 16014309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 16024309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 16034309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 16044a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1605c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 16064a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1607d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1608d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 160957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1610b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 161157d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 161257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1613d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void routeAids(String aid, int route) { 1614d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen Message msg = mHandler.obtainMessage(); 1615d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.what = MSG_ROUTE_AID; 1616d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.arg1 = route; 1617d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.obj = aid; 1618d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendMessage(msg); 1619d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1620d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1621d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void unrouteAids(String aid) { 1622d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen sendMessage(MSG_UNROUTE_AID, aid); 1623d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1624d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1625d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void commitRouting() { 1626d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING); 1627d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1628d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 16294309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales public boolean sendData(byte[] data) { 16304309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales return mDeviceHost.sendRawFrame(data); 16319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 16329f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1633b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1634b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1635b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1636b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1637b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1638b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1639b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 16403fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1641b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1642b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 164331949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 1644d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_ROUTE_AID: { 1645d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen int route = msg.arg1; 1646d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1647d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.routeAid(hexStringToBytes(aid), route); 1648d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen // Restart polling config 1649d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1650d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1651d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_UNROUTE_AID: { 1652d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1653d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.unrouteAid(hexStringToBytes(aid)); 1654d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1655d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 16569340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case MSG_INVOKE_BEAM: { 16579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj); 16589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen break; 16599340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 1660d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_COMMIT_ROUTING: { 1661f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen boolean commit = false; 1662f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen synchronized (NfcService.this) { 1663f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen if (mCurrentDiscoveryParameters.shouldEnableDiscovery()) { 1664f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen commit = true; 1665f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } else { 1666f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen Log.d(TAG, "Not committing routing because discovery is disabled."); 1667f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1668f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1669f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen if (commit) { 1670f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen mDeviceHost.commitRouting(); 1671f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1672d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1673d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 167431949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 167531949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 167631949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 167731949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 167831949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 167931949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 168031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 16814309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Tag tag = Tag.createMockTag(new byte[]{0x00}, 16824309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales new int[]{TagTechnology.NDEF}, 16834309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales new Bundle[]{extras}); 168431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 168531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 168632cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales int dispatchStatus = mNfcDispatcher.dispatchTag(tag); 168732cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales if (dispatchStatus == NfcDispatcher.DISPATCH_SUCCESS) { 1688d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 168932cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales } else if (dispatchStatus == NfcDispatcher.DISPATCH_FAIL) { 1690d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 169131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 169231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 169331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 169457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 169631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 169731949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 169831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams readerParams = null; 169931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY; 1700a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales DeviceHost.TagDisconnectedCallback callback = 1701a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales new DeviceHost.TagDisconnectedCallback() { 1702a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales @Override 1703a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales public void onTagDisconnected(long handle) { 1704a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales applyRouting(false); 1705a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1706a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales }; 1707c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 170831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen readerParams = mReaderModeParams; 1709c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 171031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (readerParams != null) { 171131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen presenceCheckDelay = readerParams.presenceCheckDelay; 171231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) { 171331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode"); 1714a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 171531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 171631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen break; 171731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 171831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 17193e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales 17203e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales boolean playSound = readerParams == null || 17213e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0; 17223e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && playSound) { 172331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_START); 1724c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 172589baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 172689baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // When these tags start containing NDEF, they will require 172789baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // the stack to deal with them in a different way, since 172889baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // they are activated only really shortly. 172989baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // For now, don't consider NDEF on these. 173089baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 1731a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 173231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 173389baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen break; 173489baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen } 1735391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 1736c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 1737391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 1738a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 173931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 174031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 174131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 1742a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 174331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 174431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 174531949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1746d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 174731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 174831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 174931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 175031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 175196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 175296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent actIntent = new Intent(ACTION_LLCP_UP); 175396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(actIntent); 175496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 175531949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 175631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 175731949217328bf2357ff044f0d18677fe588c790cNick Pelly 175831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 175996e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 176096e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent deactIntent = new Intent(ACTION_LLCP_DOWN); 176196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(deactIntent); 176296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 176331949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 176431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 176531949217328bf2357ff044f0d18677fe588c790cNick Pelly 176631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 176731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 176831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 176931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 177031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 177131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 177231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 177331949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 177431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 177531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 177631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 177731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 177831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178231949217328bf2357ff044f0d18677fe588c790cNick Pelly 178377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 178431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 178557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen case MSG_LLCP_LINK_FIRST_PACKET: 178657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mP2pLinkManager.onLlcpFirstPacketReceived(); 178757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen break; 1788c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen case MSG_RF_FIELD_ACTIVATED: 1789c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Intent fieldOnIntent = new Intent(ACTION_RF_FIELD_ON_DETECTED); 1790c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendNfcEeAccessProtectedBroadcast(fieldOnIntent); 1791c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 1792c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen case MSG_RF_FIELD_DEACTIVATED: 1793c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Intent fieldOffIntent = new Intent(ACTION_RF_FIELD_OFF_DETECTED); 1794c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendNfcEeAccessProtectedBroadcast(fieldOffIntent); 1795dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen break; 179642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales case MSG_RESUME_POLLING: 179742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mNfcAdapter.resumePolling(); 1798c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 179931949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 180031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 180131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 180231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1803b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1804d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1805c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private void sendNfcEeAccessProtectedBroadcast(Intent intent) { 1806c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1807c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Resume app switches so the receivers can start activites without delay 1808c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfcDispatcher.resumeAppSwitches(); 1809c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1810c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 1811c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (PackageInfo pkg : mInstalledPackages) { 1812c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (pkg != null && pkg.applicationInfo != null) { 1813c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 1814c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen intent.setPackage(pkg.packageName); 1815c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext.sendBroadcast(intent); 1816c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1817c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1818c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1819c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1820c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1821c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1822d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1823d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1824d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1825d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1826d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1827d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1828d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1829d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1830d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1831d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1832d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 183331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 183431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 183531949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1836d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 183777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1838d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1839d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1840d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1841d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1842d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1843d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1844d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1845d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1846d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1847d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1848d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1849d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1850d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1851d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1852d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1853d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1854d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1855d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1856d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1857d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1858d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1859d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1860d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1861d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 186231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 186331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 186431949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1865d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 186677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1867d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1868d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1869d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1870d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1871d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1872d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1873d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1874d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1875d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1876d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 187731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) { 1878f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1879f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1880f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 18813dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams != null) { 188231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen try { 188331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 188431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_END); 188531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 18863dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams.callback != null) { 18873dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen readerParams.callback.onTagDiscovered(tag); 18883dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 18893dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } else { 18903dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Follow normal dispatch below 18913dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } 189231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } catch (RemoteException e) { 18930799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.e(TAG, "Reader mode remote has died, falling back.", e); 18943dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Intentional fall-through 18953dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } catch (Exception e) { 18963dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Catch any other exception 18970799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.e(TAG, "App exception, not dispatching.", e); 18983dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 189931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 190031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 190132cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales int dispatchResult = mNfcDispatcher.dispatchTag(tag); 190232cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales if (dispatchResult == NfcDispatcher.DISPATCH_FAIL) { 1903f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1904d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 190532cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales } else if (dispatchResult == NfcDispatcher.DISPATCH_SUCCESS) { 1906d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 19073fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 19083fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1909b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1910b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1911b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 191249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1913fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 1914fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1915fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 1916fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 1917fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 1918fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 1919fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1920fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 1921161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1922fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 1923fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1924525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 1925525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 1926525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRouting(false); 1927525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 1928525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 1929161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1930fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 19317c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19327c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19337c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19347c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 1935525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1936525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 1937525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onReceive(Context context, Intent intent) { 1938525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project String action = intent.getAction(); 1939c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen if (action.equals(Intent.ACTION_SCREEN_ON) 1940525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_SCREEN_OFF) 1941525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_USER_PRESENT)) { 1942525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 19434309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales int screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1944525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_SCREEN_OFF)) { 19454309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1946525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 19474309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = mKeyguard.isKeyguardLocked() 19484309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales ? ScreenStateHelper.SCREEN_STATE_ON_LOCKED 19494309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1950525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 19514309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1952525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1953525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 195431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 195531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 195631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 195731949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 195831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 195931949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 196031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 196131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 196231949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 196331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 19641668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 19651668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 196631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 196731949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 196831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 196931949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 197031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 19713859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 1972d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1973d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales synchronized (this) { 1974d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mUserId = userId; 1975d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales } 1976d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mP2pLinkManager.onUserSwitched(getUserId()); 1977341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 1978af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onUserSwitched(getUserId()); 19794358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen } 1980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 198331949217328bf2357ff044f0d18677fe588c790cNick Pelly 1984c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() { 1985c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen @Override 1986c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onReceive(Context context, Intent intent) { 1987c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String action = intent.getAction(); 1988c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 1989c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 1990c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 1991c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 1992c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen updatePackageCache(); 1993c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1994c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 1995c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 1996c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccessControl.invalidateCache(); 1997c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1998c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1999c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 2000c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen }; 2001c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 2002b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz private final BroadcastReceiver mPolicyReceiver = new BroadcastReceiver() { 2003b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz @Override 2004b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz public void onReceive(Context context, Intent intent){ 2005b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz String action = intent.getAction(); 2006b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 2007b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz .equals(action)) { 2008b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz enforceBeamShareActivityPolicy(context, 2009b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz new UserHandle(getSendingUserId()), mIsNdefPushEnabled); 2010b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 2011b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 2012b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz }; 2013c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 20144309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 20154309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * Returns true if airplane mode is currently on 20164309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 201731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 20187d8987f233985a5ff29226890e11012275d325f5Martijn Coenen return Settings.System.getInt(mContentResolver, 20197d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 202031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 202131949217328bf2357ff044f0d18677fe588c790cNick Pelly 20224309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 20234309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * for debugging only - no i18n 20244309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 202531949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 202631949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 202731949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 202831949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 202931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 203031949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 203131949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 203231949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 203331949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 203431949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 203531949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 203631949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 203731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 203831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 203931949217328bf2357ff044f0d18677fe588c790cNick Pelly 204031949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 204150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 204250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 204350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 204450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 204550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 204650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 204750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 204850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 204931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 205031949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 20510b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 20524309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState)); 205331949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 205431949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 20550799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales pw.println(mCurrentDiscoveryParameters); 205677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 2057341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 2058af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.dump(fd, pw, args); 2059341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen } 2060391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 206156f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 206231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 206331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 206474180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 2065