NfcService.java revision d92037714c289cffb9ed1e6e6df36cd3b7292a21
1f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly/* 2f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Copyright (C) 2010 The Android Open Source Project 3f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * 4f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 5f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * you may not use this file except in compliance with the License. 6f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * You may obtain a copy of the License at 7f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * 8f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * http://www.apache.org/licenses/LICENSE-2.0 9f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * 10f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * Unless required by applicable law or agreed to in writing, software 11f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 12f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * See the License for the specific language governing permissions and 14f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly * limitations under the License. 15f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly */ 16f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellypackage com.android.nfc; 18f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 19f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.DeviceHostListener; 204a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.DeviceHost.LlcpServerSocket; 214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamiltonimport com.android.nfc.DeviceHost.LlcpSocket; 22f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.NfcDepEndpoint; 23f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamiltonimport com.android.nfc.DeviceHost.TagEndpoint; 2481c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcManager; 2581c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport com.android.nfc.nxp.NativeNfcSecureElement; 268afd14d3b23d3124c48ee275ba2845aede6542a1Jeff Hamiltonimport com.android.nfc3.R; 27d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pellyimport android.app.Application; 29275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parksimport android.app.KeyguardManager; 3005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3113d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 3205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName; 3331949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3413d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 3513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 3893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 39d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 40d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 413fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 42f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 43f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 442094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4649d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 47f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 48f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 500e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5124dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 529d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 53aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5481c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 557c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 5650effe4645b6ea57a1dc90777995f41dd9624e55Kenny Rootimport android.os.Binder; 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; 65d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 66f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 67f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 6831949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 6957d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 7031949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 7131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 723ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 7384e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 7431949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 753ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 7677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pellypublic class NfcService extends Application implements DeviceHostListener { 77bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 78bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 798d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson static final boolean DBG = true; 8076a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 81fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 82d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 83fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 84bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 85bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 86bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 87bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 88a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; 8993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required"; 90bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 9177d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly public static final String PREF = "NfcServicePrefs"; 92f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 93f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final String PREF_NFC_ON = "nfc_on"; 94f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final boolean NFC_ON_DEFAULT = true; 95f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 96f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final boolean NDEF_PUSH_ON_DEFAULT = true; 97f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final String PREF_FIRST_BEAM = "first_beam"; 98f5c40bdbcabbe81fdf43a24cd82be919ffb5de04Jeff Hamilton static final String PREF_FIRST_BOOT = "first_boot"; 99a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 100b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 101b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 102b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 103b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 104b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 105b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 106c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 107c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1082c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1092c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1102c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 111b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 11231949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 11331949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 11431949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 11531949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 11631949217328bf2357ff044f0d18677fe588c790cNick Pelly 11749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 11849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 11949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 12049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1217efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 122d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen // for use with playSound() 123d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_START = 0; 124d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_END = 1; 125d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public static final int SOUND_ERROR = 2; 126d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 12749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 13149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 13249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 13349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 13449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1352c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1362c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1372c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1382c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1392c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1402c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 1412c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 1422c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1432c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 1442c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 1452c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 1462c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 1472c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 14831949217328bf2357ff044f0d18677fe588c790cNick Pelly //TODO: dont hardcode this 14931949217328bf2357ff044f0d18677fe588c790cNick Pelly private static final byte[][] EE_WIPE_APDUS = { 15031949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 15131949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 15231949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 15331949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 15431949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 15531949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 15631949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 15731949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 15831949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 15931949217328bf2357ff044f0d18677fe588c790cNick Pelly }; 16049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 16149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 16249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 1630bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 16449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 16549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 1660bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 167d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 168d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 169d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 1702f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 1712f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 17284e1e0adc2516afd35ebab029a52e764e0490559Jason parks private HashSet<String> mSePackages = new HashSet<String>(); 17331949217328bf2357ff044f0d18677fe588c790cNick Pelly private boolean mIsScreenUnlocked; 1740b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly private boolean mIsNdefPushEnabled; 17531949217328bf2357ff044f0d18677fe588c790cNick Pelly 17631949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 17731949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 17831949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 17931949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1802f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 1812f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 18205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 1834a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 1840e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 1850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 186533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly private PowerManager.WakeLock mWakeLock; 187d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 188d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 189d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 190d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 19177d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly P2pLinkManager mP2pLinkManager; 1924a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 1934a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 1944a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 19531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 19631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 1972ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 19876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 199275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 200d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 201d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 202d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 20393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 20493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton int admin = context.checkCallingOrSelfPermission(ADMIN_PERM); 20593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM); 20693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton if (admin != PackageManager.PERMISSION_GRANTED 20793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton && nfcee != PackageManager.PERMISSION_GRANTED) { 20893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton throw new SecurityException(ADMIN_PERM_ERROR); 20993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 21093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 21193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 21293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceNfceeAdminPerm(Context context) { 21393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR); 21493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 21593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 216d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 217d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 218d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 219f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2200e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 221f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 222f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 223f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 224f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 225f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 226f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 227f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 228d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 229f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 230f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 231f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 232f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 234f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 235f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 236d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 237f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_CARD_EMULATION, aid); 239f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 241f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 242f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 247f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 252d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 254f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 255f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 257d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 258f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 260f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 261f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 262d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 263f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 268442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 269442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 270442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 271442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 272442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 273442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 274442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 275442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 276442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 277442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 278442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 279442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 280442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 281442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 282442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 2830e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onCreate() { 2842f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onCreate(); 2852f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 2864a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 2874a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 288ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 2894a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 2902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 2912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 292d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 293d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 2940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mContext = this; 295f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost = new NativeNfcManager(this, this); 29674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 29777d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager = new P2pLinkManager(mContext); 29877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mNfcDispatcher = new NfcDispatcher(this, mP2pLinkManager); 29924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 3000bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas mSecureElement = new NativeNfcSecureElement(); 301eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 3020bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 303275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 3040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 305f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 30631949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 3070b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 308f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 309275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 310275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 311533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 312275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 31331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = pm.isScreenOn() && !mKeyguard.isKeyguardLocked(); 314533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 315d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 317eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 31865945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 31965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 320bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 321275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 32231949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 323275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 324bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 325bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter = new IntentFilter(); 326bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 327bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addDataScheme("package"); 328bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 329275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 3300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 33131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 33231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 33331949217328bf2357ff044f0d18677fe588c790cNick Pelly 334d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void initSoundPool() { 335d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 336d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 337d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 338d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mStartSound = mSoundPool.load(this, R.raw.start, 1); 339d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mEndSound = mSoundPool.load(this, R.raw.end, 1); 340d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mErrorSound = mSoundPool.load(this, R.raw.error, 1); 341d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 342d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 343d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 344d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 345d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen void releaseSoundPool() { 346d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen synchronized(this) { 347d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool != null) { 348d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.release(); 349d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool = null; 350d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 351d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 352d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 353d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 35431949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 35531949217328bf2357ff044f0d18677fe588c790cNick Pelly final ContentResolver resolver = mContext.getContentResolver(); 35631949217328bf2357ff044f0d18677fe588c790cNick Pelly final String airplaneModeRadios = Settings.System.getString(resolver, 35731949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_RADIOS); 35831949217328bf2357ff044f0d18677fe588c790cNick Pelly final String toggleableRadios = Settings.System.getString(resolver, 35931949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 36031949217328bf2357ff044f0d18677fe588c790cNick Pelly 36131949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 36231949217328bf2357ff044f0d18677fe588c790cNick Pelly airplaneModeRadios.contains(Settings.System.RADIO_NFC); 36331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 36431949217328bf2357ff044f0d18677fe588c790cNick Pelly toggleableRadios.contains(Settings.System.RADIO_NFC); 36531949217328bf2357ff044f0d18677fe588c790cNick Pelly 36631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 36731949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 36831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 36931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 37031949217328bf2357ff044f0d18677fe588c790cNick Pelly 37131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 37231949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 37331949217328bf2357ff044f0d18677fe588c790cNick Pelly * 37431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 37531949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 37631949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 37731949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 37831949217328bf2357ff044f0d18677fe588c790cNick Pelly * 37931949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 38031949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 38131949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 38231949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 38331949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 38431949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 38531949217328bf2357ff044f0d18677fe588c790cNick Pelly * 38631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 38731949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 38831949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 38931949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 39131949217328bf2357ff044f0d18677fe588c790cNick Pelly * 39231949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 39331949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 39431949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 39531949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 39631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 39731949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 39831949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 39931949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 40031949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 40131949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 40231949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 40331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 40431949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 40531949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 40631949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 40731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 40831949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 40931949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 41031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 41131949217328bf2357ff044f0d18677fe588c790cNick Pelly 4124467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4134467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4144467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4154467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4164467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4174467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4184467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4194467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4204467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 42231949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 42731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 42831949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 4290fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"checking on firmware download"); 43031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 43131949217328bf2357ff044f0d18677fe588c790cNick Pelly !(mIsAirplaneSensitive && isAirplaneModeOn())) { 4320fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is on. Doing normal stuff"); 43331949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 4340fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton } else { 4350fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton Log.d(TAG,"NFC is off. Checking firmware version"); 4360fe7049a3224aa7b29cc980be07387e17607b0deJeff Hamilton mDeviceHost.checkFirmware(); 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 43831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 43931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 44031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 44231949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 44331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 44431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 44531949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 44631949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 44731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 44831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 449d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 450d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 451d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly 45531949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 45731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 46031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 46131949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 46231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 46331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 46531949217328bf2357ff044f0d18677fe588c790cNick Pelly 46631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mDeviceHost.initialize()) { 46731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Error enabling NFC"); 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 47431949217328bf2357ff044f0d18677fe588c790cNick Pelly 4750b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 47631949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 47731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47831949217328bf2357ff044f0d18677fe588c790cNick Pelly 479d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen initSoundPool(); 480d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 48131949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 48231949217328bf2357ff044f0d18677fe588c790cNick Pelly applyRouting(); 48331949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 48431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 48531949217328bf2357ff044f0d18677fe588c790cNick Pelly 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 49131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 49231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 49331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 49431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 49531949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 49631949217328bf2357ff044f0d18677fe588c790cNick Pelly 49731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 49831949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 49931949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 50031949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 50131949217328bf2357ff044f0d18677fe588c790cNick Pelly WatchDogThread watchDog = new WatchDogThread(); 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly 50477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, false); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly 50631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 50831949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 50931949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 51031949217328bf2357ff044f0d18677fe588c790cNick Pelly applyRouting(); 51131949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly 5130b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly 51531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 52131949217328bf2357ff044f0d18677fe588c790cNick Pelly 522d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen releaseSoundPool(); 523d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen 52431949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 52531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly 52731949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 52831949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 52931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[][]apdus = EE_WIPE_APDUS; 53031949217328bf2357ff044f0d18677fe588c790cNick Pelly 53131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 53231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 53331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!enableInternal()) { 534ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 53531949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 536f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 537f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 53831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Executing SE wipe"); 53931949217328bf2357ff044f0d18677fe588c790cNick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 54031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (handle == 0) { 54131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Could not open the secure element"); 54231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 54431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly for (byte[] cmd : apdus) { 551ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly byte[] resp = mSecureElement.doTransceive(handle, cmd); 552ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly if (resp == null) { 553ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 554ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly break; 555ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.resetTimeouts(); 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly mSecureElement.doDisconnect(handle); 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56531949217328bf2357ff044f0d18677fe588c790cNick Pelly 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 57231949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 57331949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 57431949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 57531949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(intent); 57631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 57931949217328bf2357ff044f0d18677fe588c790cNick Pelly 58031949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 58131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 58231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 58331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 58431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 5850e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 5860e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 587d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen public void playSound(int sound) { 588d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 589d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen if (mSoundPool == null) { 590d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen Log.w(TAG, "Not playing sound when NFC is disabled"); 591d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen return; 592d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 593d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen switch (sound) { 594d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_START: 595d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 596d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 597d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_END: 598d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 599d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 600d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen case SOUND_ERROR: 601d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 602d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen break; 603d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen } 604d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 605d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 606d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 6070e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 6082f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly public void onTerminate() { 6092f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onTerminate(); 6102f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // NFC application is persistent, it should not be destroyed by framework 6110e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly Log.wtf(TAG, "NFC service is under attack!"); 6120e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6144a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 615fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6160e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 61793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6180e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 61931949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 62031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 62131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "denying enable() request (airplane mode)"); 62231949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 623f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 62431949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 62531949217328bf2357ff044f0d18677fe588c790cNick Pelly 62631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 627f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 628f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 629fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean disable() throws RemoteException { 63193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 63331949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(false); 63431949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 63531949217328bf2357ff044f0d18677fe588c790cNick Pelly 63631949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 637f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 638f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 639fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6400b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean isNdefPushEnabled() throws RemoteException { 64131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 6420b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return mIsNdefPushEnabled; 64331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 644d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 645d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 646d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 6470b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean enableNdefPush() throws RemoteException { 648d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 649d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 6500b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (mIsNdefPushEnabled) { 65131949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6530b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "enabling NDEF Push"); 6540b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 6560b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = true; 65731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 65877d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(true, true); 659d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 660d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 661d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 662d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 663d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 664d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 6650b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public boolean disableNdefPush() throws RemoteException { 666d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 667d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 6680b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (!mIsNdefPushEnabled) { 66931949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 67031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 6710b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly Log.i(TAG, "disabling NDEF Push"); 6720b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 67331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 6740b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mIsNdefPushEnabled = false; 67531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 67677d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.enableDisable(false, true); 677d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 678d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 679d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 680d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 681d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 682d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 6830b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundDispatch(PendingIntent intent, 68424dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 68505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 686a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 6870b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly // Short-cut the disable path 6880b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly if (intent == null && filters == null && techListsParcel == null) { 6890b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(null, null, null); 6900b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly return; 691ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 692a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 693a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 694a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 695a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 696a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 697a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 698a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 699a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 700a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 701a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 702a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 703a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 704a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 705a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 70624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 70724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 70824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 70924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 71024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 71149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 7120b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 7132094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7142094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 7152094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 7160b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly public void setForegroundNdefPush(NdefMessage msg, INdefPushCallback callback) { 717ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7180b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly mP2pLinkManager.setNdefToSend(msg, callback); 719ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 720ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 721ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 7220e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 723d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7240e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 7250e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 727fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 72849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public INfcAdapterExtras getNfcAdapterExtrasInterface() { 72993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 73049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 7310bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 7320bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 733fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 73431949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 73531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 73631949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 73731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 73831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 73931949217328bf2357ff044f0d18677fe588c790cNick Pelly 74031949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 74131949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 74231949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 7430e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly }; 7450e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 7464a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 747fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 748f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 749d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 750bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 751f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 752f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 75331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 754f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 755f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 756f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 757f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 758f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 759f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 760b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 761b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 76221545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 763b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 764f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 765f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 76649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 767f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 768f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 769f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 770fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 771ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 772d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 773bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 774f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 775f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 77631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 777f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 778f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 779f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 780f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 781f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 782b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 783b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 784f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 785ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 7861b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen if (technology == TagTechnology.NFC_B) { 7871b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen return ErrorCodes.ERROR_NOT_SUPPORTED; 7881b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen } 7891b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen 790ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 791ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 792ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 793ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 794ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 795ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 796ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 797ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 798f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 799f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 800fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 801aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 802aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 803aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 804f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 805aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 806aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 80731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 808aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 809aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 810aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 811aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 812f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 813aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 814aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 815aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 816aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 817aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 818aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 819aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 820aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 821aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 822aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 823aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 824b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 825d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 826bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 827f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 82831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 829f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 832f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 833f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 834f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 835b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 836f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 837f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 838f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 839f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 840fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 841f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public byte[] getUid(int nativeHandle) throws RemoteException { 842f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 843f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] uid; 844f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 845f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 84631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 847f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 848f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 849f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 850f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 851f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 852f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 853f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly uid = tag.getUid(); 854f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return uid; 855f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 856f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 857f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 858f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 859fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 860b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 861f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 862b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 863b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 86431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 865b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 866b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 867b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 868b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 869f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 870b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 871b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 872b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 873b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 874ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 875b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 876b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 877fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 878f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 879f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 881f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 88231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 8832c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 884f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 885f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 886f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 887f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 8883ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 8892c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 8902c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 89270bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 893f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 894f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 895fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 8969d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 89797c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 898d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 899bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 900f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 901f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 902f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 903f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 90431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 906f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 909f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 911bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen // Check if length is within limits 912bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 913bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 914bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 9159d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 9169d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 917bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen int result; 918bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen if (response != null) { 919bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_SUCCESS; 920bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else if (targetLost[0] == 1) { 921bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_TAGLOST; 922bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } else { 923bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen result = TransceiveResult.RESULT_FAILURE; 924bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 925bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return new TransceiveResult(result, response); 926f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 927f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 928f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 929f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 930fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9313fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 932d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 933bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 934f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 935f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 936f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 93731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 940f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 941f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 942f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 943f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 944f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 945f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 947f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 948f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 949f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 950f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 951f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 952f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 953f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 957f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 959fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 961d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 962bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 963f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 964f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 965f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 96631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 967f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 968f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 969f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 970f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 971f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 975f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 976f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 977f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 978f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 979f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 982f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 984fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int getLastError(int nativeHandle) throws RemoteException { 986f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton return(mDeviceHost.doGetLastError()); 987f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 989fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9903fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 9913fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 992f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 994fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9953fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 99603ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 99703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 998f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 99903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 100003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 100131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 100203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 100303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 100403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 100503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1006f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 100703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 100803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 100903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 101003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1011f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 101203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1013f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 101403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 101503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1016f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 10180aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 10190aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 10200aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10210aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1022f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 10230aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10240aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 102531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10260aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 10270aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10280aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10290aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1030f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10310aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 10320aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10330aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10340aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10350aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 10360aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1037f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 10380aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10390aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10400aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10410aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10421b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 10433fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 10443fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10453fb14d0868594c78a777e805545209636814e223Martijn Coenen 1046f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 10473fb14d0868594c78a777e805545209636814e223Martijn Coenen 10483fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 104931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10503fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 10513fb14d0868594c78a777e805545209636814e223Martijn Coenen } 10523fb14d0868594c78a777e805545209636814e223Martijn Coenen 10533fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1054f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10553fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 10563fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 10573fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 10583fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 10593fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 10603fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 10613fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 10623fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 10633fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 10643fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 10653fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1066f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton NdefMessage[] msgs = tag.findAndReadNdef(); 10673fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 10683fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 10694a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 10703fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 10713fb14d0868594c78a777e805545209636814e223Martijn Coenen } 10723fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 10733fb14d0868594c78a777e805545209636814e223Martijn Coenen } 10743fb14d0868594c78a777e805545209636814e223Martijn Coenen 10751b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1076fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 10771b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1078f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1079fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1080fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1081fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1082fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1083fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1084dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1085dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1086dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1087358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1088358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1089358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1090358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1091358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1092358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1093358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1094dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1095dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1096dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1097f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 10981b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 1099bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1100bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1101bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1102bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1103bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1104bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.canMakeReadOnly(ndefType); 1105bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 1106bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1107bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen @Override 1108bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen public int getMaxTransceiveLength(int tech) throws RemoteException { 1109bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1110bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen 1111bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen return mDeviceHost.getMaxTransceiveLength(tech); 1112bf6e5d1655d5ad524a8ec007413c7011ed969df8Martijn Coenen } 11130e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly }; 1114f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1115dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException { 1116dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1117dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1118dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1119dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1120dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly synchronized(NfcService.this) { 112131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1122dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1123dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1124dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1125dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1126dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1127dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) { 1128dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1129dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1130dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1131f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1132dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mSecureElement.doDisconnect(mOpenEe.handle); 1133dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1134dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1135dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly applyRouting(); 1136dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1137dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1138dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 11394a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 114049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 114149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 114249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 114349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 114449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 114549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeIoException(IOException e) { 114649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 114749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", -1); 114849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putString("m", e.getMessage()); 114949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 115049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11510bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1152bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 115349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle open(IBinder b) throws RemoteException { 115493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 1155bd555ee64250126b60b24814120a2049943920caNick Pelly 115649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 115749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 115849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly _open(b); 115949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 116049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 116149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 11620bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 116349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 116449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11650bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 116649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private void _open(IBinder b) throws IOException, RemoteException { 116749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 116831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 116949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC adapter is disabled"); 117049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 117149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 117249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE already open"); 117349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 117549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 117649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (handle == 0) { 117749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE failed to open"); 117849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1179f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1180ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 118149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle); 118249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 118349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 118449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 118549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 118649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 118784e1e0adc2516afd35ebab029a52e764e0490559Jason parks 118884e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 118984e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 119084e1e0adc2516afd35ebab029a52e764e0490559Jason parks for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 119184e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 119284e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 119349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11940bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 11950bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1196bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 119749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle close() throws RemoteException { 119893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 11990bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 120049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 120149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 1202dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly _nfcEeClose(true, getCallingPid()); 120349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 120449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 120549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12060bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 120749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 120849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1210bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 121149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle transceive(byte[] in) throws RemoteException { 121293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 1213bd555ee64250126b60b24814120a2049943920caNick Pelly 121449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 121549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 121649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 121749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 121849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 121949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 122049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 122149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12220bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 122349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 122449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 122649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private byte[] _transceive(byte[] data) throws IOException, RemoteException { 122749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 122831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 122949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 123049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 123149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe == null){ 123249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 123349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 123449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 123549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 123649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12380bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 123949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mSecureElement.doTransceive(mOpenEe.handle, data); 12400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12410bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1242bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 124349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int getCardEmulationRoute() throws RemoteException { 124493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 124549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 12460bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12470bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1248bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 124949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void setCardEmulationRoute(int route) throws RemoteException { 125093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 125149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 125249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 12530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1254bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1255bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 12565a8844da9bc569aa7289426bf7b96e7eef90abf5Nick Pelly public void authenticate(byte[] token) throws RemoteException { 1257bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks NfcService.enforceNfceeAdminPerm(mContext); 1258bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 12590bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas }; 12600bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 126149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 126249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 126349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 126449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 126549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public OpenSecureElement(int pid, int handle) { 126649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 126749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 126849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1269bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 127049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 127149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 127249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 127349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 12740bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 1275dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly _nfcEeClose(false, -1); 1276dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 12770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12790bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12800bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 128131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 128231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 128331949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1284e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1285aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1286aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 128731949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 12882edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean mWatchDogCanceled = false; 12892edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 12902edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 12912edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean slept = false; 12922edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly while (!slept) { 12932edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly try { 12942edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Thread.sleep(10000); 12952edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly slept = true; 12962edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } catch (InterruptedException e) { } 12972edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 12982edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly synchronized (this) { 12992edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly if (!mWatchDogCanceled) { 13002edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly // Trigger watch-dog 13012edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Log.e(TAG, "Watch dog triggered"); 13022083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly mDeviceHost.doAbort(); 13032edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13042edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13052edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13062edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 13072edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly mWatchDogCanceled = true; 13082edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13092edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13102edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 131149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** apply NFC discovery and EE routing */ 1312e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton void applyRouting() { 1313e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton synchronized (this) { 1314e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (!isNfcEnabled() || mOpenEe != null) { 1315e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton return; 1316e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1317e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (mIsScreenUnlocked) { 1318e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1319e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton Log.d(TAG, "NFC-EE routing ON"); 1320e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doSelectSecureElement(); 1321e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } else { 1322e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton Log.d(TAG, "NFC-EE routing OFF"); 1323e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doDeselectSecureElement(); 1324e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1325e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton Log.d(TAG, "NFC-C polling ON"); 1326e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.enableDiscovery(); 1327221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } else { 132849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Log.d(TAG, "NFC-EE routing OFF"); 1329f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.doDeselectSecureElement(); 1330e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton Log.d(TAG, "NFC-C polling OFF"); 1331e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.disableDiscovery(); 1332221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 133365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 133465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 133565945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 13362436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 133731949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 133831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1339a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1340a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 134131949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 134231949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 134331949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 134431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 134531949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 134631949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 134731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 134831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 134931949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 135031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 135131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 135231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 135331949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 135431949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 135531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 135631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 135731949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 135831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 135931949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 136031949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 136131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 136231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 136331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1364bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1365bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1366bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1367bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1368bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 136931949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 137031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 137131949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 137231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 137331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 13742f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 137531949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 13760e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1377f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1378f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 137931949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 138031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 138131949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1382f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1383b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1384b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 138531949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 138631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 138731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 138831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1389f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1390f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1391d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 13924a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 13934a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton throws IOException, LlcpException { 13944a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1395d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1396d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1397d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 13984a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 13994a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton int linearBufferLength) throws IOException, LlcpException { 14004a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1401d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1402d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 140357d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1404b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 140557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 140657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1407b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1408b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1409b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1410b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1411b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1412b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1413b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 14143fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1415b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1416b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 141731949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 141831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 141931949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 142031949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 142131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 142231949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 142331949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 142431949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 142531949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 142631949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 142731949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 142831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 142931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 143031949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag, 143131949217328bf2357ff044f0d18677fe588c790cNick Pelly new NdefMessage[] { ndefMsg }); 143231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 1433d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 143477d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly } else { 1435d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 143631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 143731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 143831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 143957d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 144031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 144131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 144231949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 1443d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_START); 144431949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage[] ndefMsgs = tag.findAndReadNdef(); 1445c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 144631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (ndefMsgs != null) { 144731949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 144831949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, ndefMsgs); 144931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 145031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 145131949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 145231949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, null); 145331949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 145431949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 1455d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 145631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 145731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 145831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 145931949217328bf2357ff044f0d18677fe588c790cNick Pelly 146031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 146131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 146231949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 146331949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 146431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 146531949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 146631949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 146731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 146814a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(aidIntent); 146931949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 147031949217328bf2357ff044f0d18677fe588c790cNick Pelly 147131949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 147231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 147331949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 147431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 147531949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 147631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 147714a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(cardRemovalIntent); 147831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 147931949217328bf2357ff044f0d18677fe588c790cNick Pelly 148031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 148131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 148231949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 148331949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 148431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 148531949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 148631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 148731949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 148831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 148931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 149014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(apduReceivedIntent); 149131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 149231949217328bf2357ff044f0d18677fe588c790cNick Pelly 149331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 149431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 149531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 149631949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 149731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 149831949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 149931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 150031949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 150131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 150231949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 150331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 150431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 150514a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(mifareAccessIntent); 150631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 1507c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 150831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 150931949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 151031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 151131949217328bf2357ff044f0d18677fe588c790cNick Pelly 151231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 151331949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 151431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 151531949217328bf2357ff044f0d18677fe588c790cNick Pelly 151631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 151731949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 151831949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 151931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 152031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 152131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 152231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 152331949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 152431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 152531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 152631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 152731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 152831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 152931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 153031949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 153131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 153231949217328bf2357ff044f0d18677fe588c790cNick Pelly 153377d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpDeactivated(); 153431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 153531949217328bf2357ff044f0d18677fe588c790cNick Pelly 153631949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 153731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 153831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 153931949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 154031949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 154131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 154231949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 154331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 154431949217328bf2357ff044f0d18677fe588c790cNick Pelly 154531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 154731949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 154831949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 154914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOnIntent); 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155231949217328bf2357ff044f0d18677fe588c790cNick Pelly 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 155714a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton sendSeBroadcast(eventFieldOffIntent); 155831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 155931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 156031949217328bf2357ff044f0d18677fe588c790cNick Pelly 156131949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 156231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 156431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1565b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1566d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 156714a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton private void sendSeBroadcast(Intent intent) { 15688e85fe445d229fba5d101b4f95fe0dfa34a8601emike wakerly mNfcDispatcher.resumeAppSwitches(); 156914a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 157014a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton mContext.sendBroadcast(intent, NFCEE_ADMIN_PERM); 157114a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton } 157214a4b124592b50dcec47d9b07232fff0188a4e02Jeff Hamilton 1573d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1574d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1575d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1576d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1577d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1578d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1579d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1580d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1581d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1582d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1583d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 158431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isZeroClickOn; 158531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 158631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 158731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1588d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 158977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1590d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1591d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1592d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1593d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1594d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1595d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1596d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1597d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1598d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1599d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1600d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1601d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1602d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1603d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1604d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1605d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1606d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1607d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1608d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1609d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1610d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1611d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1612d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1613d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 161431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isZeroClickOn; 161531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 161631949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 161731949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1618d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 161977d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.onLlcpActivated(); 1620d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1621d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1622d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1623d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1624d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1625d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1626d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1627d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1628d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1629d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1630f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) { 1631f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1632f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1633f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 163476a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly if (!mNfcDispatcher.dispatchTag(tag, msgs)) { 1635f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1636d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_ERROR); 1637d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1638d92037714c289cffb9ed1e6e6df36cd3b7292a21Martijn Coenen playSound(SOUND_END); 16393fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 16403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1641b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1642b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1643b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 164449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 164531949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 1646fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1647275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks protected Void doInBackground(Boolean... params) { 1648275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]); 1649275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 1650275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (params != null && params.length > 0 && params[0]) { 1651161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly synchronized (NfcService.this) { 165231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsScreenUnlocked) { 165331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = true; 1654275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks applyRouting(); 1655275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } else { 1656275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "Ignoring enable request"); 1657275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } 1658161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 16597c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } else { 1660533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock.acquire(); 1661161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly synchronized (NfcService.this) { 166231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsScreenUnlocked) { 166331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = false; 1664e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton// applyRouting(); 1665e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton /* 1666e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * TODO undo this after the LLCP stack is fixed. 1667e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * This is done locally here since the LLCP stack is still using 1668e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * globals without holding any locks, and if we attempt to change 1669e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * the NFCEE routing while the target is still connected (and it's 1670e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * a P2P target) the async LLCP callbacks will crash since the routing 1671e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * manipulation code is overwriting globals it relies on. This hack should 1672e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton * be removed when the LLCP stack is fixed. 1673e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton */ 16747bbabb2deebbc498c635f690c5283201da549247Martijn Coenen if (isNfcEnabled() && mOpenEe == null) { 16757bbabb2deebbc498c635f690c5283201da549247Martijn Coenen Log.d(TAG, "NFC-C polling OFF"); 16767bbabb2deebbc498c635f690c5283201da549247Martijn Coenen mDeviceHost.disableDiscovery(); 16777bbabb2deebbc498c635f690c5283201da549247Martijn Coenen maybeDisconnectTarget(); 1678e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton Log.d(TAG, "NFC-EE routing OFF"); 1679e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton mDeviceHost.doDeselectSecureElement(); 1680e0b5fcb7e6422d1a788c48dd8f2936832ab8b397Jeff Hamilton } 1681275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } else { 1682275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "Ignoring disable request"); 1683275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } 1684161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1685533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock.release(); 16867c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16877c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly return null; 16887c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16897c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16907c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 16910e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 16920e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 16930e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 169431949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 169531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (action.equals( 1696f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 1697ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1699f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 170049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 1701f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 170231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1703275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // Only enable if the screen is unlocked. If the screen is locked 1704275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // Intent.ACTION_USER_PRESENT will be broadcast when the screen is 1705275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // unlocked. 170636a1e42f1811692fb734bc5f015e294eab0bed4cJeff Hamilton boolean enable = !mKeyguard.isKeyguardLocked(); 1707275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 17086ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // Perform discovery enable in thread to protect against ANR when the 17096ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // NFC stack wedges. This is *not* the correct way to fix this issue - 17106ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // configuration of the local NFC adapter should be very quick and should 17116ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // be safe on the main thread, and the NFC stack should not wedge. 1712275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(enable); 171331949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 17147c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // Perform discovery disable in thread to protect against ANR when the 17157c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // NFC stack wedges. This is *not* the correct way to fix this issue - 17167c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // configuration of the local NFC adapter should be very quick and should 17177c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // be safe on the main thread, and the NFC stack should not wedge. 1718275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(Boolean.FALSE); 171931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1720275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // The user has unlocked the screen. Enabled! 1721275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(Boolean.TRUE); 172231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 172331949217328bf2357ff044f0d18677fe588c790cNick Pelly EnableDisableTask eeWipeTask = new EnableDisableTask(); 172431949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.execute(TASK_EE_WIPE); 172531949217328bf2357ff044f0d18677fe588c790cNick Pelly try { 172631949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.get(); // blocks until EE wipe is complete 172731949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (ExecutionException e) { 172831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 172931949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (InterruptedException e) { 173031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 173131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 173231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 17337a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 17347a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (dataRemoved) { 17357a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton Uri data = intent.getData(); 17367a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (data == null) return; 17377a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton String packageName = data.getSchemeSpecificPart(); 17387a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 17397a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton synchronized (NfcService.this) { 174084e1e0adc2516afd35ebab029a52e764e0490559Jason parks if (mSePackages.contains(packageName)) { 174131949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_EE_WIPE); 174284e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.remove(packageName); 17437a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 1744bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1745bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 174631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 174731949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 174831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 174931949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 175031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 175131949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 175231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 175331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 175431949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 175531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 175631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 175731949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 175831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 175931949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 176031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1761f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1762f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1763f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 176431949217328bf2357ff044f0d18677fe588c790cNick Pelly 176531949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 176631949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 176731949217328bf2357ff044f0d18677fe588c790cNick Pelly return Settings.System.getInt(mContext.getContentResolver(), 176831949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_ON, 0) == 1; 176931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 177031949217328bf2357ff044f0d18677fe588c790cNick Pelly 177131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** for debugging only - no il8n */ 177231949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 177331949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 177431949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 177531949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 177631949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 177731949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 177831949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 178231949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 178331949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 178431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 178631949217328bf2357ff044f0d18677fe588c790cNick Pelly 178731949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 178850effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 178950effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root != PackageManager.PERMISSION_GRANTED) { 179050effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root pw.println("Permission Denial: can't dump nfc from from pid=" 179150effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 179250effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root + " without permission " + android.Manifest.permission.DUMP); 179350effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root return; 179450effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root } 179550effe4645b6ea57a1dc90777995f41dd9624e55Kenny Root 179631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 179731949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 17980b3b8ab69835cb66c96691dae3ba9b75705980a5Nick Pelly pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 179931949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsScreenUnlocked=" + mIsScreenUnlocked); 180031949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 180131949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 180277d0b56bfa6a4e4e1449c476a1141a7486f34ad9Nick Pelly mP2pLinkManager.dump(fd, pw, args); 180356f2a7bc39a14487f01cbf2d131ba3cde4126f2dMartijn Coenen pw.println(mDeviceHost.dump()); 180431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 180531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 180674180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 1807