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; 83d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenenimport java.util.ArrayList; 843ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 85c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.util.List; 8628a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Moralesimport java.util.Map; 87c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenenimport java.util.NoSuchElementException; 883ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 89d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen 90525c260303268a83da4c3413b953d13c9084e834The Android Open Source Projectpublic class NfcService implements DeviceHostListener { 91c05387ef4e6d6d024b03254e7e2ea5ad001cf2d2Jeff Hamilton static final boolean DBG = false; 9276a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 93fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 94d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 95fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 9677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 97f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 98416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 99416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NFC_ON_DEFAULT = true; 100416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 101416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 102416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 103416e2fc507d696486a127f932105b3b95519d0cbJeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 1041668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 105a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 106b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 107c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_ACTIVATION = 1; 108c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_DEACTIVATED = 2; 109c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_MOCK_NDEF = 3; 110c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_LLCP_LINK_FIRST_PACKET = 4; 111c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_ROUTE_AID = 5; 112c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_UNROUTE_AID = 6; 113c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_COMMIT_ROUTING = 7; 114c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_INVOKE_BEAM = 8; 115c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_RF_FIELD_ACTIVATED = 9; 116c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final int MSG_RF_FIELD_DEACTIVATED = 10; 117e276d3323d755d8bdaccd59a551332c064970215Andres Morales static final int MSG_RESUME_POLLING = 11; 11842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 11942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales static final long MAX_POLLING_PAUSE_TIMEOUT = 40000; 120b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 12131949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 12231949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 12331949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 124c3981b9a0b39faed474480bc3dbd3e33bbd50b99Martijn Coenen 125a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales // Polling technology masks 126a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_A = 0x01; 127a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_B = 0x02; 128a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_F = 0x04; 129a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_ISO15693 = 0x08; 130a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_B_PRIME = 0x10; 131a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales static final int NFC_POLL_KOVIO = 0x20; 132fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1330799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // minimum screen state that enables NFC polling 1340799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1350799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 136525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for NFC controller to initialize before watchdog 137525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off. This time is chosen large, because firmware download 138525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // may be a part of initialization. 139525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int INIT_WATCHDOG_MS = 90000; 140525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 141525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Time to wait for routing to be applied before watchdog 142525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // goes off 143525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project static final int ROUTING_WATCHDOG_MS = 10000; 144525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 14531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen // Default delay used for presence checks 14631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen static final int DEFAULT_PRESENCE_CHECK_DELAY = 125; 14731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 14834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // The amount of time we wait before manually launching 14934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // the Beam animation when called through the share menu. 15034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen static final int INVOKE_BEAM_DELAY_MS = 1000; 15134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen 152c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // RF field events as defined in NFC extras 153c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public static final String ACTION_RF_FIELD_ON_DETECTED = 154c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 155c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public static final String ACTION_RF_FIELD_OFF_DETECTED = 156c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 157c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 158d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 159d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 160d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 161d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 162d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 16396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_UP = 16496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_UP"; 16596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 16696e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen public static final String ACTION_LLCP_DOWN = 16796e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen "com.android.nfc.action.LLCP_DOWN"; 16896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 16942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales // Timeout to re-apply routing if a tag was present and we postponed it 17042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales private static final int APPLY_ROUTING_RETRY_TIMEOUT_MS = 5000; 17142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 1725c452dad7b24f28223414ce5e953bfcab782570eAndres Morales private final UserManager mUserManager; 1735c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 17449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 17549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 176c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen private final ReaderModeDeathRecipient mReaderModeDeathRecipient = 177c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen new ReaderModeDeathRecipient(); 17816ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales private final NfcUnlockManager mNfcUnlockManager; 1790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 180c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private final NfceeAccessControl mNfceeAccessControl; 181c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 182c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen List<PackageInfo> mInstalledPackages; // cached version of installed packages 183c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1842f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 185fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 186fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly int mScreenState; 1877d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 188fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly boolean mIsNdefPushEnabled; 189ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen NfcDiscoveryParameters mCurrentDiscoveryParameters = 190ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen NfcDiscoveryParameters.getNfcOffParameters(); 19128a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 19231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams mReaderModeParams; 19331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 19431949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 19531949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 19631949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 19731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1982f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 19905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 2004a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 2010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 2020e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 203525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private PowerManager.WakeLock mRoutingWakeLock; 204525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 205d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 206d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 207d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 208d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 20977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 2104a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 2114a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 21231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 21331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 21496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen boolean mIsDebugBuild; 2150a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen boolean mIsHceCapable; 21642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales boolean mPollingPaused; 2172ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 21876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 219fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly private PowerManager mPowerManager; 220275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 221b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales private HandoverDataParser mHandoverDataParser; 2227d8987f233985a5ff29226890e11012275d325f5Martijn Coenen private ContentResolver mContentResolver; 223af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen private CardEmulationManager mCardEmulationManager; 22428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 2254309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales private ScreenStateHelper mScreenStateHelper; 22634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen private ForegroundUtils mForegroundUtils; 227d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 22828a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales private int mUserId; 2294309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales private static NfcService sService; 23089c893312d524f50c47b0d32071f3de8631197f3Martijn Coenen 231d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 232d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 233d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 236f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 237f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 239f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 241f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 243d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 2449f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationActivated() { 245af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 246af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationActivated(); 2470a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2489f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2499f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2509f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 2519f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationData(byte[] data) { 252af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 253af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationData(data); 2540a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2559f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2569f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2579f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen @Override 2589f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen public void onHostCardEmulationDeactivated() { 259af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen if (mCardEmulationManager != null) { 260af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onHostCardEmulationDeactivated(); 2610a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 2629f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 2639f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 2649f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen /** 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 268f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 271f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 273f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 274f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 275d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 276f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 277f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 278f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 279f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 28057a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen /** 28157a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen * Notifies P2P Device detected, first packet received over LLCP link 28257a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen */ 28357a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen @Override 28457a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 28557a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 28657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen } 28757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen 288c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen @Override 289c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onRemoteFieldActivated() { 290c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendMessage(NfcService.MSG_RF_FIELD_ACTIVATED, null); 291c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 292c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 293c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onRemoteFieldDeactivated() { 294c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendMessage(NfcService.MSG_RF_FIELD_DEACTIVATED, null); 295c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 296c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 29731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen final class ReaderModeParams { 29831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int flags; 29931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public IAppCallback callback; 30031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public int presenceCheckDelay; 30131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 30231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen 303525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public NfcService(Application nfcApplication) { 304d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mUserId = ActivityManager.getCurrentUser(); 3054309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mContext = nfcApplication; 3064309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales 3074a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 3084a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 3092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 3102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 311d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 312d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 3134309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mScreenStateHelper = new ScreenStateHelper(mContext); 3147d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mContentResolver = mContext.getContentResolver(); 315525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost = new NativeNfcManager(mContext, this); 31674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 31716ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales mNfcUnlockManager = NfcUnlockManager.getInstance(); 31816ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 319b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mHandoverDataParser = new HandoverDataParser(); 3207d8987f233985a5ff29226890e11012275d325f5Martijn Coenen boolean isNfcProvisioningEnabled = false; 3217d8987f233985a5ff29226890e11012275d325f5Martijn Coenen try { 3227d8987f233985a5ff29226890e11012275d325f5Martijn Coenen isNfcProvisioningEnabled = mContext.getResources().getBoolean( 3237d8987f233985a5ff29226890e11012275d325f5Martijn Coenen R.bool.enable_nfc_provisioning); 3247d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } catch (NotFoundException e) { 3257d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 3267d8987f233985a5ff29226890e11012275d325f5Martijn Coenen 3277d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (isNfcProvisioningEnabled) { 3287d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 3297d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 3307d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } else { 3317d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = false; 3327d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 333525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 334b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode); 335b82d80d891077ccd74729e4143925a66eb89eef2Andres Morales mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser, 336525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 33724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 338525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 3390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 340f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 341c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccessControl = new NfceeAccessControl(mContext); 342c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 34331949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3440b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 345a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(mIsNdefPushEnabled); 346f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 34796e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); 34896e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen 349525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 350525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 351525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock = mPowerManager.newWakeLock( 3524309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 353275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 354525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 3555c452dad7b24f28223414ce5e953bfcab782570eAndres Morales mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 3565c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 3574309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mScreenState = mScreenStateHelper.checkScreenState(); 358533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 359d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 360f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 361525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Intents for all users 362c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); 36365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 364275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 3653859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen filter.addAction(Intent.ACTION_USER_SWITCHED); 36631949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 367525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 3680e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 369c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); 370c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); 371c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 372c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 373c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter = new IntentFilter(); 374c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 375c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 376c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ownerFilter.addDataScheme("package"); 377c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext.registerReceiver(mOwnerReceiver, ownerFilter); 378c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 379b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 380b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null); 381b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz 382c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen updatePackageCache(); 383c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 3840a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen PackageManager pm = mContext.getPackageManager(); 385341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION); 3860a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 387af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager = new CardEmulationManager(mContext); 388a56a84a384db51809101e149d83bf41b5e198ca0Martijn Coenen } 38934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen mForegroundUtils = ForegroundUtils.getInstance(); 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 39131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 39231949217328bf2357ff044f0d18677fe588c790cNick Pelly 393d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 3944309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (this) { 395d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 396d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 397525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 398525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 399525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 400d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 401d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 402d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 403d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 404d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 4054309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (this) { 406d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 407d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 408d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 409d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 410d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 411d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 412d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 41331949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 4147d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String airplaneModeRadios = Settings.System.getString(mContentResolver, 4157d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_RADIOS); 4167d8987f233985a5ff29226890e11012275d325f5Martijn Coenen final String toggleableRadios = Settings.System.getString(mContentResolver, 4177d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 41831949217328bf2357ff044f0d18677fe588c790cNick Pelly 41931949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 4207d8987f233985a5ff29226890e11012275d325f5Martijn Coenen airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 4224309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales toggleableRadios.contains(Settings.Global.RADIO_NFC); 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 42731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 42831949217328bf2357ff044f0d18677fe588c790cNick Pelly 429c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen void updatePackageCache() { 430c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen PackageManager pm = mContext.getPackageManager(); 431c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER); 432c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 433c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mInstalledPackages = packages; 434c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 435c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 436c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 43831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 4394309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 44031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 44231949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 44331949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 4444309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 44531949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 44631949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 44731949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 44831949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 44931949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 45031949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 4514309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 45531949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 4574309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * <p/> 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 46031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 46131949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 46231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 46331949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 46531949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 46631949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 46731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 47431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47531949217328bf2357ff044f0d18677fe588c790cNick Pelly 4764467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4774467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4784467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4794467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4804467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4814467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4824467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4834467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4844467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 48531949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 49131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 49231949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 4934309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "checking on firmware download"); 4941668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 49531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 4961668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 4974309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "NFC is on. Doing normal stuff"); 49831949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 4990fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 5004309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Log.d(TAG, "NFC is off. Checking firmware version"); 5010fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 50431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 50631949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 50831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 50931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 510d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 511d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 512d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 51331949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51531949217328bf2357ff044f0d18677fe588c790cNick Pelly 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 52131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 52231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 52331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 52531949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly 527525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 528525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.start(); 529525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 530525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 531525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 532304a6342ee7e5620d3b50d988755c035f1686dc2Martijn Coenen if (!mDeviceHost.initialize()) { 533525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project Log.w(TAG, "Error enabling NFC"); 534525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project updateState(NfcAdapter.STATE_OFF); 535525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project return false; 536525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 537525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 538525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 539525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 540525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 541525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project watchDog.cancel(); 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly 5440a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen if (mIsHceCapable) { 5450a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen // Generate the initial card emulation routing table 546af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onNfcEnabled(); 5470a9487f8aad77ed5f1a8f142b690396446858247Martijn Coenen } 548d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 5494309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 5510b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 55331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55431949217328bf2357ff044f0d18677fe588c790cNick Pelly 555d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 556d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 5580c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 559fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 56531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 57231949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 57331949217328bf2357ff044f0d18677fe588c790cNick Pelly 57431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 57631949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 578525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 57931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 58031949217328bf2357ff044f0d18677fe588c790cNick Pelly 581953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen if (mIsHceCapable) { 582af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onNfcDisabled(); 583953c3dd151419d497205246d4bfa8a818d39d00aMartijn Coenen } 584d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 58577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 58631949217328bf2357ff044f0d18677fe588c790cNick Pelly 58731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 58831949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 58931949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 59031949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 59131949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 59231949217328bf2357ff044f0d18677fe588c790cNick Pelly 5930b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 59431949217328bf2357ff044f0d18677fe588c790cNick Pelly 595ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen 59631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 59731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 59831949217328bf2357ff044f0d18677fe588c790cNick Pelly 59931949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 60031949217328bf2357ff044f0d18677fe588c790cNick Pelly 601ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen synchronized (NfcService.this) { 602ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen mCurrentDiscoveryParameters = NfcDiscoveryParameters.getNfcOffParameters(); 603ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen updateState(NfcAdapter.STATE_OFF); 604ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen } 60531949217328bf2357ff044f0d18677fe588c790cNick Pelly 606d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 607d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 60831949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 60931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61031949217328bf2357ff044f0d18677fe588c790cNick Pelly 61131949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 6122a3f6f141fdaf746a81ce850a8ab0ef251041966mike wakerly synchronized (NfcService.this) { 61331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 61431949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 61531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 61631949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 61731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 61831949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 61931949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 620525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 62731949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 62831949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 62931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 632d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 633d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 634d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 635d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 636d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 637d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 638d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 639d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 640d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 641d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 642d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 643d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 644d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 645d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 646d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 647d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 648d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 649d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 650d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 651d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 652d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales synchronized int getUserId() { 653d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales return mUserId; 654d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales } 655d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales 656a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen void setBeamShareActivityState(boolean enabled) { 657b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 658b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // Propagate the state change to all user profiles related to the current 659b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // user. Note that the list returned by getUserProfiles contains the 660b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz // current user. 661b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz List <UserHandle> luh = um.getUserProfiles(); 662b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz for (UserHandle uh : luh){ 663b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz enforceBeamShareActivityPolicy(mContext, uh, enabled); 664b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 665b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 666b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz 667b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz void enforceBeamShareActivityPolicy(Context context, UserHandle uh, 668b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz boolean isGlobalEnabled){ 669b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 670b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 671b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz boolean isActiveForUser = 672b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) && 673b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz isGlobalEnabled; 674b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz if (DBG){ 675b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz Log.d(TAG, "Enforcing a policy change on user: " + uh + 676b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz ", isActiveForUser = " + isActiveForUser); 677b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 678b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz try { 679b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz mIpm.setComponentEnabledSetting(new ComponentName( 680b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz BeamShareActivity.class.getPackageName$(), 681b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz BeamShareActivity.class.getName()), 682b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz isActiveForUser ? 683b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 684b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 685b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz PackageManager.DONT_KILL_APP, 686b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz uh.getIdentifier()); 687b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } catch (RemoteException e) { 688b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz Log.w(TAG, "Unable to change Beam status for user " + uh); 689b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 690a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen } 6910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6924a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 693fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 6954309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 6960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 69731949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 6981668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen 6991668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (mIsAirplaneSensitive && isAirplaneModeOn()) { 7001668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen if (!mIsAirplaneToggleable) { 7011668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen Log.i(TAG, "denying enable() request (airplane mode)"); 7021668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen return false; 7031668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen } 7041668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen // Make sure the override survives a reboot 7051668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 7061668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 707f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 70831949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 70931949217328bf2357ff044f0d18677fe588c790cNick Pelly 71031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 711f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 712f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 713fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 714290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi public boolean disable(boolean saveState) throws RemoteException { 7154309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 717290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi if (saveState) { 718290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi saveNfcOnSetting(false); 719290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi } 720290a6967a04f49dc3969dced9f82c1636a7e7902Sunil Jogi 72131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 72231949217328bf2357ff044f0d18677fe588c790cNick Pelly 72331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 724f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 725f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 726dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen @Override 72742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales public void pausePolling(int timeoutInMs) { 72842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 72942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 73042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales if (timeoutInMs <= 0 || timeoutInMs > MAX_POLLING_PAUSE_TIMEOUT) { 73142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales Log.e(TAG, "Refusing to pause polling for " + timeoutInMs + "ms."); 73242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales return; 73342c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 73442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 73542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales synchronized (NfcService.this) { 73642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mPollingPaused = true; 73742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mDeviceHost.disableDiscovery(); 73842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.sendMessageDelayed( 73942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.obtainMessage(MSG_RESUME_POLLING), timeoutInMs); 74042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 74142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 74242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 743dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen @Override 74442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales public void resumePolling() { 74542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 74642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 74742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales synchronized (NfcService.this) { 74842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales if (!mPollingPaused) { 74942c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales return; 75042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 75142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 75242c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.removeMessages(MSG_RESUME_POLLING); 75342c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mPollingPaused = false; 75442c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales new ApplyRoutingTask().execute(); 75542c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 75642c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales } 75742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales 758fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 7590b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 76031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 7619993a5a96a862cea4512509b413d0de6cacb7c14Nick Pelly return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 76231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 763d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 764d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 765d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7660b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 7674309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7684309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 7690b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 77031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 77131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7720b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 7730b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 77431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7750b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 776a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(true); 77731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 77877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 779d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 780d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 781d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 782d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 783d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 784d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 7850b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 7864309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 7874309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales synchronized (NfcService.this) { 7880b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 78931949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 79031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 7910b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 7920b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 79331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 7940b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 795a7a09dbc3e681de3054d61b544753cbb8406c649Martijn Coenen setBeamShareActivityState(false); 79631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 79777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 798d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 799d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 800d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 801d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 802d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 803d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 8040b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 80524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 8064309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 807a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 8080b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 8090b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 8100b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 8110b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 812ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 813a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 814a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 815a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 816a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 817a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 818a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 819a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 820a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 821a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 822a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 823a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 824a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 825a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 826a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 82724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 82824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 82924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 83024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 83124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 83249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 8330b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 8342094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 8352094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 8369340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8372094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 83831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setAppCallback(IAppCallback callback) { 8394309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 8405c452dad7b24f28223414ce5e953bfcab782570eAndres Morales 841b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales // don't allow Beam for managed profiles, or devices with a device owner or policy owner 842b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId()); 84365860bb589c5802ffadb14540670408d6c8dfaa9Benjamin Franz if(!mUserManager.hasUserRestriction( 844b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle())) { 8455c452dad7b24f28223414ce5e953bfcab782570eAndres Morales mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 846b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales } else if (DBG) { 847b42756d47f39774a07654f68af27bf3cc2c41511Andres Morales Log.d(TAG, "Disabling default Beam behavior"); 8485c452dad7b24f28223414ce5e953bfcab782570eAndres Morales } 849ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 850ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 851ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 8525d0258c45b65f1051add13d35ff6adc7b6e67697Martijn Coenen public void verifyNfcPermission() { 8535d0258c45b65f1051add13d35ff6adc7b6e67697Martijn Coenen NfcPermissions.enforceUserPermissions(mContext); 8545d0258c45b65f1051add13d35ff6adc7b6e67697Martijn Coenen } 8555d0258c45b65f1051add13d35ff6adc7b6e67697Martijn Coenen 8565d0258c45b65f1051add13d35ff6adc7b6e67697Martijn Coenen @Override 8579340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen public void invokeBeam() { 8589340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen NfcPermissions.enforceUserPermissions(mContext); 8599340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 86034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen if (mForegroundUtils.isInForeground(Binder.getCallingUid())) { 8619340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mP2pLinkManager.onManualBeamInvoke(null); 8629340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } else { 8639340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen Log.e(TAG, "Calling activity not in foreground."); 8649340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8659340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 8669340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen 8679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen @Override 86834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen public void invokeBeamInternal(BeamShareData shareData) { 86934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen NfcPermissions.enforceAdminPermissions(mContext); 87034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen Message msg = Message.obtain(); 87134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen msg.what = MSG_INVOKE_BEAM; 87234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen msg.obj = shareData; 87334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // We have to send this message delayed for two reasons: 87434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 1) This is an IPC call from BeamShareActivity, which is 87534322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // running when the user has invoked Beam through the 87634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // share menu. As soon as BeamShareActivity closes, the UI 87734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // will need some time to rebuild the original Activity. 87834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Waiting here for a while gives a better chance of the UI 87934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // having been rebuilt, which means the screenshot that the 88034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Beam animation is using will be more accurate. 88134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 2) Similarly, because the Activity that launched BeamShareActivity 88234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // with an ACTION_SEND intent is now in paused state, the NDEF 88334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // callbacks that it has registered may no longer be valid. 88434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Allowing the original Activity to resume will make sure we 88534322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // it has a chance to re-register the NDEF message / callback, 88634322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // so we share the right data. 88734322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // 88834322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // Note that this is somewhat of a hack because the delay may not actually 88934322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // be long enough for 2) on very slow devices, but there's no better 89034322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen // way to do this right now without additional framework changes. 89134322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS); 89234322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen } 89334322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen 89434322b73c1e09907cb007e86bae77c744b338cd7Martijn Coenen @Override 8950e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 8960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 8970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 8980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 899fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 900a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen public INfcCardEmulation getNfcCardEmulationInterface() { 90135b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen if (mIsHceCapable) { 90235b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen return mCardEmulationManager.getNfcCardEmulationInterface(); 90335b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen } else { 90435b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen return null; 90535b004b876ba3d10a8f204beeaa282289ad9b13bMartijn Coenen } 906a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen } 907a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen 908a0b908c58b5ab0d242ccc545d14573901774bd29Martijn Coenen @Override 90931949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 91031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 91131949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 91231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 91331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 91431949217328bf2357ff044f0d18677fe588c790cNick Pelly 91531949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 91631949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 91731949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 9180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 919391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly 920391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly @Override 921ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly public void dispatch(Tag tag) throws RemoteException { 9224309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 923ea78e5beebff19ece23870b4ff5e5fd69d61aaa1Nick Pelly mNfcDispatcher.dispatchTag(tag); 924391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly } 9250c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen 9260c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen @Override 9270c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 9284309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 9290c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pInitiatorModes(initiatorModes); 9300c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen mDeviceHost.setP2pTargetModes(targetModes); 9310799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales applyRouting(true); 9320c39284106d29e8852197d163dcc95c01da29f0dMartijn Coenen } 933c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 934c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 93531f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras) 93631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen throws RemoteException { 937c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 938c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen if (flags != 0) { 939c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 94031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = new ReaderModeParams(); 94131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.callback = callback; 94231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams.flags = flags; 9434309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales mReaderModeParams.presenceCheckDelay = extras != null 9444309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 9454309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales DEFAULT_PRESENCE_CHECK_DELAY)) 9464309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales : DEFAULT_PRESENCE_CHECK_DELAY; 947c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.linkToDeath(mReaderModeDeathRecipient, 0); 948c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (RemoteException e) { 949c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Remote binder has already died."); 950c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen return; 951c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 952c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } else { 953c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen try { 95431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 955c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen binder.unlinkToDeath(mReaderModeDeathRecipient, 0); 956c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } catch (NoSuchElementException e) { 957c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen Log.e(TAG, "Reader mode Binder was never registered."); 958c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 959c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 960c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 961c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 962c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 963c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen 964c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen @Override 965c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) throws RemoteException { 966c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen // nfc-extras implementation is no longer present in AOSP. 967c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen return null; 968c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen } 96928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 97028a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales @Override 97116ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales public void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, int[] techList) { 97216ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales NfcPermissions.enforceAdminPermissions(mContext); 97316ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 97416ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales int lockscreenPollMask = computeLockscreenPollMask(techList); 97516ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales synchronized (NfcService.this) { 97616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales mNfcUnlockManager.addUnlockHandler(unlockHandler, lockscreenPollMask); 97716ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 97816ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 97916ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales applyRouting(false); 98016ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 98116ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 98216ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales @Override 983af05d4f78bca45a13f54444a67c1da09bdd599a3Andres Morales public void removeNfcUnlockHandler(INfcUnlockHandler token) throws RemoteException { 98416ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales synchronized (NfcService.this) { 985af05d4f78bca45a13f54444a67c1da09bdd599a3Andres Morales mNfcUnlockManager.removeUnlockHandler(token.asBinder()); 98616ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 98716ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 98816ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales applyRouting(false); 98916ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales } 99016ee2fe0e0f6d2f811bd06c37cbd53c8b395e6d6Andres Morales 99128a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales private int computeLockscreenPollMask(int[] techList) { 99228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 99328a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>(); 99428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 99528a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A); 996616980fe53b2595f6320d344a6b8ebb0e898485eAndres Morales techCodeToMask.put(TagTechnology.NFC_B, NfcService.NFC_POLL_B); 99728a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693); 99828a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F); 99928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO); 100028a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 100128a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales int mask = 0; 100228a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 100328a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales for (int i = 0; i < techList.length; i++) { 100428a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales if (techCodeToMask.containsKey(techList[i])) { 100528a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales mask |= techCodeToMask.get(techList[i]).intValue(); 100628a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 100728a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 100828a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales 100928a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales return mask; 101028a49f0de26c4cc6f0b8c30dc67bebcb1a3110b6Andres Morales } 1011c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1012c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen 1013c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen final class ReaderModeDeathRecipient implements IBinder.DeathRecipient { 1014c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen @Override 1015c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen public void binderDied() { 1016c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 101731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (mReaderModeParams != null) { 101831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen mReaderModeParams = null; 1019c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen applyRouting(false); 1020c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1021c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1022c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 1023c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 10240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 10254a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 1026fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 10284309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1029bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1030f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1031f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 103231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1034f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1035f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1036f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1037f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1039b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 1040b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 104121545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 1042b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 1043f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1044f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 1045fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1046f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 1047f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1048f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1049fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1050ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 10514309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1052bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1053f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1054f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 105531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1056f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1057f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1058f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1059f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1060f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1061b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1062b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 1063f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1064ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 1065cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen if (!tag.isPresent()) { 1066cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1067cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen } 1068cd7f018ec0cff0fcdcfe1399aa2398b809f2e35eMartijn Coenen 1069ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 1070ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 1071ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 1072ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 1073ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 1074ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 1075ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1076ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 1077f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1078f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1079fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1080aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 10814309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1082aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1083f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1084aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1085aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 108631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1087aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 1088aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1089aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1090aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 1091f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1092aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 1093aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 1094aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 1095aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 1096aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1097aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1098aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1099aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 1100aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 1101aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 1102aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 1103b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 11044309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1105bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1106f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 110731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1108f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1109f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1110f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1111f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1112f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1113f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1114b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 1115f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1116f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1117f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1118f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1119fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1120b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 1121f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1122b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1123b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 112431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1125b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1126b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1127b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1128b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 1129f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1130b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 1131b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 1132b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1133b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1134ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 1135b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1136b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1137fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1138f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 11394309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1140182152b054d555fc4ac5d5c2cd2367cb8c205782Martijn Coenen 1141f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1142f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1143f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 114431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 11452c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1146f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1147f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1148f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1149f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 11503ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 11512c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 11522c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 1153f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 115470bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 1155f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1156f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1157fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11589d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 115997c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 11604309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1161bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1162f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 1163f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 1164f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1165f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 116631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1167f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1168f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1169f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1170f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1171f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1172f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1173bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 1174bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1175bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1176bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 11779d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 11789d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 1179bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 1180bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 1181bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 1182bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 1183bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 1184bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 1185bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 1186bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1187bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 1188f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1189f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1190f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1191f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1192fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 11933fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 11944309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1195bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1196f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1197f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1198f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 119931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1200f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1201f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1202f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1203f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1204f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1205f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 1206f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 1207f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 1208f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1209f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 1210f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1211f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 1212f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 1213f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 1214f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 1215f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1216f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1217f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1218f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1220f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1221fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12223fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 12234309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1224bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1225f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1226f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1227f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 122831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1229f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1230f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1231f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1232f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1234f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1235f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1236f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1237f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1238791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1239791ab7ad5b2fafaa4587d9ba7fb0fe39a815f278Martijn Coenen 1240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1241f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1243f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1244f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1245f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1246f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1247f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1248fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12493fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 12503fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1251f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1252f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1253fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 12543fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 12554309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 125603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1257f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 125803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 125903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 126031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 126103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 126203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 126303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 126403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 126603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 126703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 126803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 126903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 127103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 127303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 127403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1275f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1276f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 12770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 12780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 12794309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 12800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1281f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 12820aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 128431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 12850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 12860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12870aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12880aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1289f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 12900aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 12910aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12920aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12930aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 12940aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 12950aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1296f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 12970aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 12980aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 12990aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 13000aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 13011b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 13023fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 13034309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 13043fb14d0868594c78a777e805545209636814e223Martijn Coenen 1305f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 13063fb14d0868594c78a777e805545209636814e223Martijn Coenen 13073fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 130831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 13093fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 13103fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13113fb14d0868594c78a777e805545209636814e223Martijn Coenen 13123fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1313f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 13143fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 13153fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 13163fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 13173fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 13183fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 13193fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 13203fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 13213fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 13223fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 13233fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 13243fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1325391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly tag.findAndReadNdef(); 13263fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 13273fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 13284a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 13293fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 13303fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13313fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 13323fb14d0868594c78a777e805545209636814e223Martijn Coenen } 13333fb14d0868594c78a777e805545209636814e223Martijn Coenen 13341b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1335fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 13364309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1337f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1338fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1339fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1340fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1341fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1342fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1343dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1344dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1345dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1346358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 13474309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1348358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1349358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1350358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1351358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1352358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1353dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 13544309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales NfcPermissions.enforceUserPermissions(mContext); 1355dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1356f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 13571b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1358bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1359bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1360bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1361bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1362bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1363bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1364bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1365bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1366bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1367bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1368ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen 1369ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen @Override 1370ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen public boolean getExtendedLengthApdusSupported() throws RemoteException { 1371ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen return mDeviceHost.getExtendedLengthApdusSupported(); 1372ba15143ff54f5078f9b2cef5804525d387c52c72Martijn Coenen } 1373c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly } 1374f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 13759a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen boolean isNfcEnabledOrShuttingDown() { 13769a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen synchronized (this) { 13779a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 13789a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13799a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen } 13809a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen 138131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 138231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 138331949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1384e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1385aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1386aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 138731949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 1388a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project final Object mCancelWaiter = new Object(); 1389525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project final int mTimeout; 1390a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project boolean mCanceled = false; 1391525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 1392525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public WatchDogThread(String threadName, int timeout) { 1393525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project super(threadName); 1394525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mTimeout = timeout; 1395525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 1396525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project 13972edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 13982edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 1399a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project try { 1400a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1401a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.wait(mTimeout); 1402a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project if (mCanceled) { 1403a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project return; 1404a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 14052edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1406a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } catch (InterruptedException e) { 1407a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project // Should not happen; fall-through to abort. 1408a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.w(TAG, "Watchdog thread interruped."); 1409a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project interrupt(); 14102edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1411a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project Log.e(TAG, "Watchdog triggered, aborting."); 1412a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mDeviceHost.doAbort(); 14132edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 1414a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project 14152edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 1416a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project synchronized (mCancelWaiter) { 1417a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCanceled = true; 1418a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project mCancelWaiter.notify(); 1419a1af766ba0b1fc5a016b796f76c29f56519dec15The Android Open Source Project } 14202edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 14212edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 14222edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 14239f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen static byte[] hexStringToBytes(String s) { 14249f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (s == null || s.length() == 0) return null; 14259f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen int len = s.length(); 14269f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen if (len % 2 != 0) { 14279f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen s = '0' + s; 14289f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen len++; 14299f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14309f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen byte[] data = new byte[len / 2]; 14319f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen for (int i = 0; i < len; i += 2) { 14329f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 14334309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales + Character.digit(s.charAt(i + 1), 16)); 14349f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14359f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen return data; 14369f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 14379f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1438fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly /** 1439fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly * Read mScreenState and apply NFC-C polling and NFC-EE routing 1440fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly */ 1441fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly void applyRouting(boolean force) { 1442e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 1443c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1444e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1445e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1446525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 14477d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (mInProvisionMode) { 14487d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mInProvisionMode = Settings.Secure.getInt(mContentResolver, 14497d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.DEVICE_PROVISIONED, 0) == 0; 14507d8987f233985a5ff29226890e11012275d325f5Martijn Coenen if (!mInProvisionMode) { 14517d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // Notify dispatcher it's fine to dispatch to any package now 14527d8987f233985a5ff29226890e11012275d325f5Martijn Coenen // and allow handover transfers. 14537d8987f233985a5ff29226890e11012275d325f5Martijn Coenen mNfcDispatcher.disableProvisioningMode(); 14547d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 14557d8987f233985a5ff29226890e11012275d325f5Martijn Coenen } 14560799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Special case: if we're transitioning to unlocked state while 14570799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // still talking to a tag, postpone re-configuration. 14580799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) { 14590799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.d(TAG, "Not updating discovery parameters, tag connected."); 146042c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING), 146142c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales APPLY_ROUTING_RETRY_TIMEOUT_MS); 14620799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales return; 14630799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 14640799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 1465f439271150e4548f116919e0254d57655421581cMartijn Coenen try { 1466f439271150e4548f116919e0254d57655421581cMartijn Coenen watchDog.start(); 14670799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Compute new polling parameters 14680799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState); 14690799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (force || !newParams.equals(mCurrentDiscoveryParameters)) { 14700799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (newParams.shouldEnableDiscovery()) { 1471ffeeef8e8d6d5f7c15f9f041d691cd9b64ddc58bMartijn Coenen boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery(); 14720799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales mDeviceHost.enableDiscovery(newParams, shouldRestart); 14730799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 1474a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales mDeviceHost.disableDiscovery(); 1475a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales } 14760799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales mCurrentDiscoveryParameters = newParams; 14770799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 14780799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.d(TAG, "Discovery configuration equal, not updating."); 1479fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly } 1480a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales } finally { 1481a1e95d30dbe8dad0a8bb333b4ca17c009fc34e2fAndres Morales watchDog.cancel(); 1482221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 148365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 148465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 148565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 14860799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) { 14870799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Recompute discovery parameters based on screen state 14880799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder(); 14890799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Polling 14900799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (screenState >= NFC_POLLING_MODE) { 14910799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Check if reader-mode is enabled 14920799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mReaderModeParams != null) { 14930799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales int techMask = 0; 14940799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0) 14950799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_A; 14960799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0) 14970799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_B; 14980799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0) 14990799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_F; 15000799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0) 15010799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_ISO15693; 15020799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0) 15030799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales techMask |= NFC_POLL_KOVIO; 15040799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales 15050799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(techMask); 15060799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableReaderMode(true); 15070799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else { 15080799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 150931b0f4653686119d74876cae5d637c5baf52b935Andres Morales paramsBuilder.setEnableP2p(mIsNdefPushEnabled); 15100799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 15110799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) { 15120799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 151331b0f4653686119d74876cae5d637c5baf52b935Andres Morales // enable P2P for MFM/EDU/Corp provisioning 151431b0f4653686119d74876cae5d637c5baf52b935Andres Morales paramsBuilder.setEnableP2p(true); 15150799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && 1516731fd8a52cec0dbe8d6ec6a4c7aa36ff52812112Andres Morales mNfcUnlockManager.isLockscreenPollingEnabled()) { 15170799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // For lock-screen tags, no low-power polling 1518731fd8a52cec0dbe8d6ec6a4c7aa36ff52812112Andres Morales paramsBuilder.setTechMask(mNfcUnlockManager.getLockscreenPollMask()); 15190799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableLowPowerDiscovery(false); 152031b0f4653686119d74876cae5d637c5baf52b935Andres Morales paramsBuilder.setEnableP2p(false); 1521a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1522a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales 15230799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) { 15240799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales // Host routing is always enabled at lock screen or later 15250799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales paramsBuilder.setEnableHostRouting(true); 15260799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales } 152731b0f4653686119d74876cae5d637c5baf52b935Andres Morales 15280799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales return paramsBuilder.build(); 1529a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1530a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales 1531a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales private boolean isTagPresent() { 1532a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales for (Object object : mObjectMap.values()) { 1533a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales if (object instanceof TagEndpoint) { 1534a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales return ((TagEndpoint) object).isPresent(); 1535a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1536a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1537a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales return false; 1538a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 15394309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 15404309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * Disconnect any target if present 15414309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 154231949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 15439a93cf5cf4b845c7983f202fe0e03615f31f6db0Martijn Coenen if (!isNfcEnabledOrShuttingDown()) { 1544a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1545a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 154731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 154831949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 154931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 155231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 155731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 155831949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 155931949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 156031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 156131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 156231949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 156431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 156531949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 156631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 156731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 156831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1569bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1570bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1571bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1572bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1573bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 157431949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 157531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 157631949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 157731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 157831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 15792f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 158031949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 15810e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1582f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1583f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 158431949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 158531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 158631949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1587f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1588b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1589b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 159031949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 159131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 159231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 159331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1594f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1595f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 15964309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 15974309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 15984309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 15994a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1600c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly throws LlcpException { 16014a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1602d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1603d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 16044309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 16054309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 16064309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 16073b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1608e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen throws LlcpException { 16093b82eef50f734cab061330f55de8b8bf5396f24bMartijn Coenen return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1610e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen } 1611e008eba3b51c5303d52bf3e9e989dfd03b18435aMartijn Coenen 16124309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 16134309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * For use by code in this process 16144309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 16154a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1616c9342fef947c49e247495b83f94f16d43cd3562cmike wakerly int linearBufferLength) throws LlcpException { 16174a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1618d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1619d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 162057d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1621b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 162257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 162357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1624d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void routeAids(String aid, int route) { 1625d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen Message msg = mHandler.obtainMessage(); 1626d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.what = MSG_ROUTE_AID; 1627d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.arg1 = route; 1628d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen msg.obj = aid; 1629d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendMessage(msg); 1630d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1631d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1632d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void unrouteAids(String aid) { 1633d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen sendMessage(MSG_UNROUTE_AID, aid); 1634d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1635d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 1636d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen public void commitRouting() { 1637d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING); 1638d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1639d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen 16404309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales public boolean sendData(byte[] data) { 16414309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales return mDeviceHost.sendRawFrame(data); 16429f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen } 16439f8f6cf9c58405ecafe2d425801e6c14088db8c7Martijn Coenen 1644b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1645b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1646b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1647b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1648b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1649b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1650b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 16513fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1652b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1653b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 165431949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 1655d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_ROUTE_AID: { 1656d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen int route = msg.arg1; 1657d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1658d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.routeAid(hexStringToBytes(aid), route); 1659d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen // Restart polling config 1660d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1661d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 1662d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_UNROUTE_AID: { 1663d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen String aid = (String) msg.obj; 1664d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen mDeviceHost.unrouteAid(hexStringToBytes(aid)); 1665d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1666d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 16679340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen case MSG_INVOKE_BEAM: { 16689340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj); 16699340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen break; 16709340b42304a512cb8fe9f4c068ba1b908876fb10Martijn Coenen } 1671d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen case MSG_COMMIT_ROUTING: { 1672f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen boolean commit = false; 1673f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen synchronized (NfcService.this) { 1674f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen if (mCurrentDiscoveryParameters.shouldEnableDiscovery()) { 1675f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen commit = true; 1676f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } else { 1677f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen Log.d(TAG, "Not committing routing because discovery is disabled."); 1678f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1679f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1680f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen if (commit) { 1681f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen mDeviceHost.commitRouting(); 1682f5c979220fadb2c3ac0bca09e16d0d281ed20eb2Martijn Coenen } 1683d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen break; 1684d53c2b599c73f7404b5a604be4d9a5449cafdd72Martijn Coenen } 168531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 168631949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 168731949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 168831949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 168931949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 169031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 169131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 16924309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales Tag tag = Tag.createMockTag(new byte[]{0x00}, 16934309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales new int[]{TagTechnology.NDEF}, 16944309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales new Bundle[]{extras}); 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 169631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 169732cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales int dispatchStatus = mNfcDispatcher.dispatchTag(tag); 169832cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales if (dispatchStatus == NfcDispatcher.DISPATCH_SUCCESS) { 1699d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 170032cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales } else if (dispatchStatus == NfcDispatcher.DISPATCH_FAIL) { 1701d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 170231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 170331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 170431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 170557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 170631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 170731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 170831949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 170931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen ReaderModeParams readerParams = null; 171031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY; 1711a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales DeviceHost.TagDisconnectedCallback callback = 1712a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales new DeviceHost.TagDisconnectedCallback() { 1713a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales @Override 1714a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales public void onTagDisconnected(long handle) { 1715a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales applyRouting(false); 1716a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales } 1717a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales }; 1718c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen synchronized (NfcService.this) { 171931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen readerParams = mReaderModeParams; 1720c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 172131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (readerParams != null) { 172231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen presenceCheckDelay = readerParams.presenceCheckDelay; 172331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) { 172431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode"); 1725a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 172631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 172731f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen break; 172831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 172931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 17303e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales 17313e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales boolean playSound = readerParams == null || 17323e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0; 17333e8b9a06407baa7c17e6f4c6bac20e0a3deaef31Andres Morales if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && playSound) { 173431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_START); 1735c4e4277a71c70e96198cb760676ad3b40f9e0e3dMartijn Coenen } 173689baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 173789baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // When these tags start containing NDEF, they will require 173889baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // the stack to deal with them in a different way, since 173989baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // they are activated only really shortly. 174089baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen // For now, don't consider NDEF on these. 174189baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 1742a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 174331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 174489baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen break; 174589baa7140bbc7899e8c2735bcfd69021a1240487Martijn Coenen } 1746391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly NdefMessage ndefMsg = tag.findAndReadNdef(); 1747c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 1748391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly if (ndefMsg != null) { 1749a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 175031f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 175131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 175231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 1753a30388eb7ddeabe1c9b85d49a65b82aac6a845caAndres Morales tag.startPresenceChecking(presenceCheckDelay, callback); 175431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen dispatchTagEndpoint(tag, readerParams); 175531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 175631949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1757d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 175831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 175931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 176031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 176131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 176296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 176396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent actIntent = new Intent(ACTION_LLCP_UP); 176496e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(actIntent); 176596e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 176631949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 176731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 176831949217328bf2357ff044f0d18677fe588c790cNick Pelly 176931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 177096e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen if (mIsDebugBuild) { 177196e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen Intent deactIntent = new Intent(ACTION_LLCP_DOWN); 177296e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen mContext.sendBroadcast(deactIntent); 177396e8f30552ad5b420cc89b97ffdc486962701afaMartijn Coenen } 177431949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 177531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 177631949217328bf2357ff044f0d18677fe588c790cNick Pelly 177731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 177831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 178231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 178331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 178431949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 178531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 178631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 178731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 179031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 179131949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 179231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 179331949217328bf2357ff044f0d18677fe588c790cNick Pelly 179477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 179531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 179657a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen case MSG_LLCP_LINK_FIRST_PACKET: 179757a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen mP2pLinkManager.onLlcpFirstPacketReceived(); 179857a44d07a3de327e8cdbbcd622118aa517313dbeMartijn Coenen break; 1799c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen case MSG_RF_FIELD_ACTIVATED: 1800c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Intent fieldOnIntent = new Intent(ACTION_RF_FIELD_ON_DETECTED); 1801c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendNfcEeAccessProtectedBroadcast(fieldOnIntent); 1802c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 1803c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen case MSG_RF_FIELD_DEACTIVATED: 1804c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Intent fieldOffIntent = new Intent(ACTION_RF_FIELD_OFF_DETECTED); 1805c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen sendNfcEeAccessProtectedBroadcast(fieldOffIntent); 1806dbcee970ef57927e73c269f573d06e2f133a34c1Martijn Coenen break; 180742c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales case MSG_RESUME_POLLING: 180842c0f35783e2849de525cdbe743c95c197fdcf50Andres Morales mNfcAdapter.resumePolling(); 1809c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 181031949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 181131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 181231949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 181331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1814b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1815d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1816c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private void sendNfcEeAccessProtectedBroadcast(Intent intent) { 1817c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1818c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Resume app switches so the receivers can start activites without delay 1819c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfcDispatcher.resumeAppSwitches(); 1820d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen ArrayList<String> matchingPackages = new ArrayList<String>(); 1821d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen ArrayList<String> preferredPackages = new ArrayList<String>(); 1822c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 1823c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (PackageInfo pkg : mInstalledPackages) { 1824c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (pkg != null && pkg.applicationInfo != null) { 1825c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (mNfceeAccessControl.check(pkg.applicationInfo)) { 1826d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen matchingPackages.add(pkg.packageName); 1827d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen if (mCardEmulationManager != null && 1828d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen mCardEmulationManager.packageHasPreferredService(pkg.packageName)) { 1829d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen preferredPackages.add(pkg.packageName); 1830d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen } 1831c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1832c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1833c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1834d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen if (preferredPackages.size() > 0) { 1835d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen // If there's any packages in here which are preferred, only 1836d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen // send field events to those packages, to prevent other apps 1837d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen // with signatures in nfcee_access.xml from acting upon the events. 1838d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen for (String packageName : preferredPackages){ 1839d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen intent.setPackage(packageName); 1840d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen mContext.sendBroadcast(intent); 1841d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen } 1842d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen } else { 1843d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen for (String packageName : matchingPackages){ 1844d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen intent.setPackage(packageName); 1845d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen mContext.sendBroadcast(intent); 1846d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen } 1847d943597d17fb8aa462b119040334478756f9e2f9Martijn Coenen } 1848c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1849c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 1850c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 1851d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1852d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1853d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1854d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1855d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1856d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 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, "Initiator 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 } else { 1869d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1870d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1871d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1872d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1873d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1874d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1875d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1876d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1877d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1878d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1879d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1880d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1881d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1882d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1883d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1884d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1885d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1886d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1887d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1888d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1889d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1890d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 189131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 189231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 189331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1894d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 189577d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1896d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1897d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1898d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1899d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1900d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1901d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1902d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1903d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1904d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1905d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 190631f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) { 1907f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1908f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1909f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 19103dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams != null) { 191131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen try { 191231f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 191331f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen playSound(SOUND_END); 191431f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 19153dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen if (readerParams.callback != null) { 19163dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen readerParams.callback.onTagDiscovered(tag); 19173dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 19183dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } else { 19193dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Follow normal dispatch below 19203dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } 192131f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } catch (RemoteException e) { 19220799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.e(TAG, "Reader mode remote has died, falling back.", e); 19233dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Intentional fall-through 19243dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen } catch (Exception e) { 19253dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen // Catch any other exception 19260799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales Log.e(TAG, "App exception, not dispatching.", e); 19273dd24ecefb71ce4f585faa002ba1054a0c6dbd06Martijn Coenen return; 192831f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 192931f39aee25964dad1038b7a9cc335d5a386113c8Martijn Coenen } 193032cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales int dispatchResult = mNfcDispatcher.dispatchTag(tag); 193132cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales if (dispatchResult == NfcDispatcher.DISPATCH_FAIL) { 1932f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1933d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 193432cdfbf250f2611bb7624c13cfd7d111a847676eAndres Morales } else if (dispatchResult == NfcDispatcher.DISPATCH_SUCCESS) { 1935d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 19363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 19373fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1938b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1939b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1940b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 194149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1942fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 1943fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1944fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly protected Void doInBackground(Integer... params) { 1945fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly synchronized (NfcService.this) { 1946fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly if (params == null || params.length != 1) { 1947fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly // force apply current routing 1948fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly applyRouting(true); 1949fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 1950161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1951fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly mScreenState = params[0].intValue(); 1952fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly 1953525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.acquire(); 1954525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project try { 1955525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project applyRouting(false); 1956525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } finally { 1957525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mRoutingWakeLock.release(); 1958161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1959fc87b4294aa0a2c85c2332a4c5229161a83961d8mike wakerly return null; 19607c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19617c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19627c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 19637c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 1964525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1965525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project @Override 1966525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project public void onReceive(Context context, Intent intent) { 1967525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project String action = intent.getAction(); 1968c8768e4b2ab114d227bd8af441d81525837f78cbMartijn Coenen if (action.equals(Intent.ACTION_SCREEN_ON) 1969525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_SCREEN_OFF) 1970525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project || action.equals(Intent.ACTION_USER_PRESENT)) { 1971525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project // Perform applyRouting() in AsyncTask to serialize blocking calls 19724309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales int screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1973525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project if (action.equals(Intent.ACTION_SCREEN_OFF)) { 19744309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1975525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 19764309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = mKeyguard.isKeyguardLocked() 19774309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales ? ScreenStateHelper.SCREEN_STATE_ON_LOCKED 19784309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1979525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 19804309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1981525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project } 198231b0f4653686119d74876cae5d637c5baf52b935Andres Morales 1983525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 198431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 198531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 198631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 198731949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 198831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 198931949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 199031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 199131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 199231949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 199331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 19941668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 19951668f533e6a2f041703919bafa4c3ceee62dbc38Martijn Coenen mPrefsEditor.apply(); 199631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 199731949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 199831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 199931949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 200031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 20013859c5cccb202c20882fb3887cfa87babb1d85a3Martijn Coenen } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 2002d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 2003d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales synchronized (this) { 2004d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mUserId = userId; 2005d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales } 2006d2604c0544f7bc26e5b2407f0215cccfffedae2cAndres Morales mP2pLinkManager.onUserSwitched(getUserId()); 2007341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 2008af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.onUserSwitched(getUserId()); 20094358172f18871d58d5bc2050e4d9d0bf9bc2d5e5Martijn Coenen } 2010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2011f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 2012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 201331949217328bf2357ff044f0d18677fe588c790cNick Pelly 201431b0f4653686119d74876cae5d637c5baf52b935Andres Morales 2015c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() { 2016c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen @Override 2017c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void onReceive(Context context, Intent intent) { 2018c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String action = intent.getAction(); 2019c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || 2020c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_PACKAGE_ADDED) || 2021c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) || 2022c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) { 2023c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen updatePackageCache(); 2024c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 2025c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 2026c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Clear the NFCEE access cache in case a UID gets recycled 2027c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccessControl.invalidateCache(); 2028c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 2029c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 2030c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 2031c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen }; 2032c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 2033b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz private final BroadcastReceiver mPolicyReceiver = new BroadcastReceiver() { 2034b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz @Override 2035b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz public void onReceive(Context context, Intent intent){ 2036b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz String action = intent.getAction(); 2037b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 2038b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz .equals(action)) { 2039b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz enforceBeamShareActivityPolicy(context, 2040b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz new UserHandle(getSendingUserId()), mIsNdefPushEnabled); 2041b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 2042b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz } 2043b708f80d56ba6d6ed110b9b7d1008563689821a4Benjamin Franz }; 2044c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 20454309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 20464309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * Returns true if airplane mode is currently on 20474309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 204831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 20497d8987f233985a5ff29226890e11012275d325f5Martijn Coenen return Settings.System.getInt(mContentResolver, 20507d8987f233985a5ff29226890e11012275d325f5Martijn Coenen Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 205131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 205231949217328bf2357ff044f0d18677fe588c790cNick Pelly 20534309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales /** 20544309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales * for debugging only - no i18n 20554309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales */ 205631949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 205731949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 205831949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 205931949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 206031949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 206131949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 206231949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 206331949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 206431949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 206531949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 206631949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 206731949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 206831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 206931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 207031949217328bf2357ff044f0d18677fe588c790cNick Pelly 207131949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 207250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 207350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 207450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 207550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 207650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 207750effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 207850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 207950effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 208031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 208131949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 20820b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 20834309f9c7c0097bdd95cf791eef78700b106dec21Andres Morales pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState)); 208431949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 208531949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 20860799bcbe2469aa6a88c6cbdf0cdee5b50e1994f0Andres Morales pw.println(mCurrentDiscoveryParameters); 208777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 2088341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen if (mIsHceCapable) { 2089af3e301d7820bc0a2447db8af16ab5335e6bd520Martijn Coenen mCardEmulationManager.dump(fd, pw, args); 2090341b2c02da8b4d2a681f3fbcc5657921ad421e32Martijn Coenen } 2091391cfe2479eca2080c14d1832599ad51cafae918Nick Pelly mNfcDispatcher.dump(fd, pw, args); 209256f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 209331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 209431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 209574180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 2096