NfcService.java revision d1936808c5f37f97fdb876836194ecbfe1cdfff5
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; 30d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.app.Notification; 31d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.app.NotificationManager; 3205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.app.PendingIntent; 3313d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.BroadcastReceiver; 3405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamiltonimport android.content.ComponentName; 3531949217328bf2357ff044f0d18677fe588c790cNick Pellyimport android.content.ContentResolver; 3613d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Context; 3713d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.Intent; 3813d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.content.IntentFilter; 390e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.content.SharedPreferences; 4093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamiltonimport android.content.pm.PackageManager; 41d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.AudioManager; 42d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamiltonimport android.media.SoundPool; 433fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamiltonimport android.net.Uri; 44f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.ErrorCodes; 45f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.FormatException; 462094515fca0cfa0ac87e9cc260d3953d416afe3eJason parksimport android.nfc.INdefPushCallback; 470e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.INfcAdapter; 4849d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.nfc.INfcAdapterExtras; 49f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.INfcTag; 50f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NdefMessage; 51f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.nfc.NfcAdapter; 520e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pellyimport android.nfc.Tag; 5324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamiltonimport android.nfc.TechListParcel; 549d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenenimport android.nfc.TransceiveResult; 55aca0d055a82da850c27f6872405602ad5f3fee7bJeff Hamiltonimport android.nfc.tech.Ndef; 5681c476dd93f059d4082c15369894d5d16fbea05dJeff Hamiltonimport android.nfc.tech.TagTechnology; 577c034a7fe7d36b1ab039af2c44717812ea02657eNick Pellyimport android.os.AsyncTask; 58b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamiltonimport android.os.Bundle; 59b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Handler; 6049d53329a0c720a7e430220d77805bc1763545b1Nick Pellyimport android.os.IBinder; 61b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneauimport android.os.Message; 62533043d1003de2f6a20a29201100d94c3c7bc9caNick Pellyimport android.os.PowerManager; 634467dca5650a170af5020c10a8ccb25f86f1007fNick Pellyimport android.os.Process; 64f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.os.RemoteException; 6513d8819d9d716c8f0ba03288d058f0bd462d70a7Nick Pellyimport android.os.ServiceManager; 66d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenenimport android.provider.Settings; 67f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pellyimport android.util.Log; 68f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 6931949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.FileDescriptor; 7057d376f1ee1a3939977b95759525585abb9601fbJeff Hamiltonimport java.io.IOException; 7131949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.io.PrintWriter; 7231949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.Arrays; 733ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamiltonimport java.util.HashMap; 7484e1e0adc2516afd35ebab029a52e764e0490559Jason parksimport java.util.HashSet; 7531949217328bf2357ff044f0d18677fe588c790cNick Pellyimport java.util.concurrent.ExecutionException; 763ca6ffff72f4599e80f85de5ae8e7f55012f38d6Jeff Hamilton 77d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamiltoninterface P2pStatusListener { 78d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton void onP2pBegin(); 79d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton void onP2pEnd(); 80d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton void onP2pError(); 81d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton} 82d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 83d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamiltonpublic class NfcService extends Application implements DeviceHostListener, P2pStatusListener { 84bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 85bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 868d6a8dce6706c6c6b3158101f2f3e94a1e0ad946Ben Dodson static final boolean DBG = true; 8776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly static final String TAG = "NfcService"; 88fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 89d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static final String SERVICE_NAME = "nfc"; 90fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks 91bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM = android.Manifest.permission.NFC; 92bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String NFC_PERM_ERROR = "NFC permission required"; 93bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 94bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 95a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; 9693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required"; 97bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 98225ae2587712b06a354b4ad4625aadc780fa4e80Martijn Coenen /*package*/ static final String PREF = "NfcServicePrefs"; 99f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1000e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private static final String PREF_NFC_ON = "nfc_on"; 1010e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private static final boolean NFC_ON_DEFAULT = true; 102d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen private static final String PREF_ZEROCLICK_ON = "zeroclick_on"; 103d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen private static final boolean ZEROCLICK_ON_DEFAULT = true; 104f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 105a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly private static final String PREF_FIRST_BOOT = "first_boot"; 106d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen private static final String PREF_FIRST_SHARE = "first_share"; 107d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen 108d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen private static final int NOTIFICATION_FIRST_SHARE = 0; 109a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly 110b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_NDEF_TAG = 0; 111b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_CARD_EMULATION = 1; 112b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_ACTIVATION = 2; 113b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_LLCP_LINK_DEACTIVATED = 3; 114b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau static final int MSG_TARGET_DESELECTED = 4; 115b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton static final int MSG_MOCK_NDEF = 7; 116c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_ACTIVATED = 8; 117c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas static final int MSG_SE_FIELD_DEACTIVATED = 9; 1182c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_APDU_RECEIVED = 10; 1192c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_EMV_CARD_REMOVAL = 11; 1202c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas static final int MSG_SE_MIFARE_ACCESS = 12; 121b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 12231949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_ENABLE = 1; 12331949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_DISABLE = 2; 12431949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_BOOT = 3; 12531949217328bf2357ff044f0d18677fe588c790cNick Pelly static final int TASK_EE_WIPE = 4; 12631949217328bf2357ff044f0d18677fe588c790cNick Pelly 12749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Copied from com.android.nfc_extras to avoid library dependency 12849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // Must keep in sync with com.android.nfc_extras 12949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_OFF = 1; 13049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 1317efbf69a37134ccbd86a1f6b4121f16b4a80eaaeNick Pelly 13249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_ON_DETECTED = 13349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 13449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_RF_FIELD_OFF_DETECTED = 13549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 13649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String ACTION_AID_SELECTED = 13749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly "com.android.nfc_extras.action.AID_SELECTED"; 13849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 13949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 1402c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_APDU_RECEIVED = 1412c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.APDU_RECEIVED"; 1422c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_APDU_BYTES = 1432c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.APDU_BYTES"; 1442c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1452c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_EMV_CARD_REMOVAL = 1462c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 1472c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 1482c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String ACTION_MIFARE_ACCESS_DETECTED = 1492c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 1502c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas public static final String EXTRA_MIFARE_BLOCK = 1512c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas "com.android.nfc_extras.extra.MIFARE_BLOCK"; 1522c37e6a839cecf5638911af357a2ea7aec6093a5Daniel Tomas 15331949217328bf2357ff044f0d18677fe588c790cNick Pelly //TODO: dont hardcode this 15431949217328bf2357ff044f0d18677fe588c790cNick Pelly private static final byte[][] EE_WIPE_APDUS = { 15531949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 15631949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 15731949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 15831949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 15931949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 16031949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 16131949217328bf2357ff044f0d18677fe588c790cNick Pelly (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 16231949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 16331949217328bf2357ff044f0d18677fe588c790cNick Pelly {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 16431949217328bf2357ff044f0d18677fe588c790cNick Pelly }; 16549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 16649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // NFC Execution Environment 16749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly // fields below are protected by this 1680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas private NativeNfcSecureElement mSecureElement; 16949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private OpenSecureElement mOpenEe; // null when EE closed 17049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private int mEeRoutingState; // contactless interface routing 1710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 172d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton // fields below must be used only on the UI thread and therefore aren't synchronized 173d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton boolean mP2pStarted = false; 174d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 1752f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are used in multiple threads and protected by synchronized(this) 1762f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 17784e1e0adc2516afd35ebab029a52e764e0490559Jason parks private HashSet<String> mSePackages = new HashSet<String>(); 17831949217328bf2357ff044f0d18677fe588c790cNick Pelly private boolean mIsScreenUnlocked; 17931949217328bf2357ff044f0d18677fe588c790cNick Pelly private boolean mIsZeroClickRequested; 18031949217328bf2357ff044f0d18677fe588c790cNick Pelly 18131949217328bf2357ff044f0d18677fe588c790cNick Pelly // mState is protected by this, however it is only modified in onCreate() 18231949217328bf2357ff044f0d18677fe588c790cNick Pelly // and the default AsyncTask thread so it is read unprotected from that 18331949217328bf2357ff044f0d18677fe588c790cNick Pelly // thread 18431949217328bf2357ff044f0d18677fe588c790cNick Pelly int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 1852f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 1862f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // fields below are final after onCreate() 18705973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton Context mContext; 1884a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton private DeviceHost mDeviceHost; 1890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences mPrefs; 1900e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private SharedPreferences.Editor mPrefsEditor; 191533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly private PowerManager.WakeLock mWakeLock; 192d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen private NotificationManager mNotificationManager; 1932ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson NdefP2pManager mP2pManager; 194d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mStartSound; 195d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mEndSound; 196d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton int mErrorSound; 197d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton SoundPool mSoundPool; // playback synchronized on this 1984a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton TagService mNfcTagService; 1994a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterService mNfcAdapter; 2004a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton NfcAdapterExtrasService mExtrasService; 20131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneSensitive; 20231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean mIsAirplaneToggleable; 2032ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson 20476a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly private NfcDispatcher mNfcDispatcher; 205275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks private KeyguardManager mKeyguard; 206d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 207d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton private static NfcService sService; 208d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 20993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceAdminPerm(Context context) { 21093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton int admin = context.checkCallingOrSelfPermission(ADMIN_PERM); 21193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM); 21293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton if (admin != PackageManager.PERMISSION_GRANTED 21393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton && nfcee != PackageManager.PERMISSION_GRANTED) { 21493d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton throw new SecurityException(ADMIN_PERM_ERROR); 21593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 21693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 21793d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 21893d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton public static void enforceNfceeAdminPerm(Context context) { 21993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR); 22093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton } 22193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton 222d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton public static NfcService getInstance() { 223d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton return sService; 224d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 225f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 2260e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 227f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteEndpointDiscovered(TagEndpoint tag) { 228f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_NDEF_TAG, tag); 229f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 230f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 231f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 232f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 233f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 234d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 235f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationDeselected() { 236f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 237f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 238f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 239f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 240f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies transaction 241f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 242d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 243f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onCardEmulationAidSelected(byte[] aid) { 244f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_CARD_EMULATION, aid); 245f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 246f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 247f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 248f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 249f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 250f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 251f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkActivated(NfcDepEndpoint device) { 252f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 253f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 254f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 255f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton /** 256f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton * Notifies P2P Device detected, to activate LLCP link 257f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton */ 258d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 259f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 260f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 261f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 262f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 263d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 264f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldActivated() { 265f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 266f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 267f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 268d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton @Override 269f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton public void onRemoteFieldDeactivated() { 270f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 271f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 272f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton 273f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton @Override 274442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeApduReceived(byte[] apdu) { 275442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 276442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 277442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 278442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 279442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeEmvCardRemoval() { 280442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 281442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 282442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 283442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 284442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly public void onSeMifareAccess(byte[] block) { 285442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 286442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly } 287442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly 288442cad40a205a63ea8797fbccaee99b2e8ab89abNick Pelly @Override 2890e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onCreate() { 2902f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onCreate(); 2912f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 2924a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcTagService = new TagService(); 2934a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton mNfcAdapter = new NfcAdapterService(); 294ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly mExtrasService = new NfcAdapterExtrasService(); 2954a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton 2962f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly Log.i(TAG, "Starting NFC service"); 2972f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly 298d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton sService = this; 299d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 300d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 301d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton mStartSound = mSoundPool.load(this, R.raw.start, 1); 302d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton mEndSound = mSoundPool.load(this, R.raw.end, 1); 303d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton mErrorSound = mSoundPool.load(this, R.raw.error, 1); 304d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 3050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mContext = this; 306f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost = new NativeNfcManager(this, this); 30774180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick 308d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton mP2pManager = new NdefP2pManager(this, this); 3092ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson mNfcDispatcher = new NfcDispatcher(this, mP2pManager); 31024dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton 3110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas mSecureElement = new NativeNfcSecureElement(); 312eab09ad7204fe1f0feaca33efccf75c1bb388708Robert Tsai mEeRoutingState = ROUTE_OFF; 3130bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 314275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 3150e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly mPrefsEditor = mPrefs.edit(); 316f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 31731949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = NfcAdapter.STATE_OFF; 31831949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsZeroClickRequested = mPrefs.getBoolean(PREF_ZEROCLICK_ON, ZEROCLICK_ON_DEFAULT); 319f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 320275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 321275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 322533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 323275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 32431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = pm.isScreenOn() && !mKeyguard.isKeyguardLocked(); 325533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly 326d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 327f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 328eead88c5e2bdd34eb33fdf2c76717f9edb9e0396Jeff Hamilton IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 32965945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_OFF); 33065945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly filter.addAction(Intent.ACTION_SCREEN_ON); 331bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 332275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks filter.addAction(Intent.ACTION_USER_PRESENT); 33331949217328bf2357ff044f0d18677fe588c790cNick Pelly registerForAirplaneMode(filter); 334275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 335bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 336bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter = new IntentFilter(); 337bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 338bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks filter.addDataScheme("package"); 339bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 340d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen mNotificationManager = (NotificationManager) this.getSystemService( 341d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen Context.NOTIFICATION_SERVICE); 342d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen 343275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks registerReceiver(mReceiver, filter); 3440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 34531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 34631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 34731949217328bf2357ff044f0d18677fe588c790cNick Pelly 34831949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerForAirplaneMode(IntentFilter filter) { 34931949217328bf2357ff044f0d18677fe588c790cNick Pelly final ContentResolver resolver = mContext.getContentResolver(); 35031949217328bf2357ff044f0d18677fe588c790cNick Pelly final String airplaneModeRadios = Settings.System.getString(resolver, 35131949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_RADIOS); 35231949217328bf2357ff044f0d18677fe588c790cNick Pelly final String toggleableRadios = Settings.System.getString(resolver, 35331949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 35431949217328bf2357ff044f0d18677fe588c790cNick Pelly 35531949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneSensitive = airplaneModeRadios == null ? true : 35631949217328bf2357ff044f0d18677fe588c790cNick Pelly airplaneModeRadios.contains(Settings.System.RADIO_NFC); 35731949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsAirplaneToggleable = toggleableRadios == null ? false : 35831949217328bf2357ff044f0d18677fe588c790cNick Pelly toggleableRadios.contains(Settings.System.RADIO_NFC); 35931949217328bf2357ff044f0d18677fe588c790cNick Pelly 36031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive) { 36131949217328bf2357ff044f0d18677fe588c790cNick Pelly filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 36231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 36331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 36431949217328bf2357ff044f0d18677fe588c790cNick Pelly 36531949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 36631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Manages tasks that involve turning on/off the NFC controller. 36731949217328bf2357ff044f0d18677fe588c790cNick Pelly * 36831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>All work that might turn the NFC adapter on or off must be done 36931949217328bf2357ff044f0d18677fe588c790cNick Pelly * through this task, to keep the handling of mState simple. 37031949217328bf2357ff044f0d18677fe588c790cNick Pelly * In other words, mState is only modified in these tasks (and we 37131949217328bf2357ff044f0d18677fe588c790cNick Pelly * don't need a lock to read it in these tasks). 37231949217328bf2357ff044f0d18677fe588c790cNick Pelly * 37331949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>These tasks are all done on the same AsyncTask background 37431949217328bf2357ff044f0d18677fe588c790cNick Pelly * thread, so they are serialized. Each task may temporarily transition 37531949217328bf2357ff044f0d18677fe588c790cNick Pelly * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 37631949217328bf2357ff044f0d18677fe588c790cNick Pelly * either STATE_ON or STATE_OFF. This way each task can be guaranteed 37731949217328bf2357ff044f0d18677fe588c790cNick Pelly * of starting in either STATE_OFF or STATE_ON, without needing to hold 37831949217328bf2357ff044f0d18677fe588c790cNick Pelly * NfcService.this for the entire task. 37931949217328bf2357ff044f0d18677fe588c790cNick Pelly * 38031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>AsyncTask's are also implicitly queued. This is useful for corner 38131949217328bf2357ff044f0d18677fe588c790cNick Pelly * cases like turning airplane mode on while TASK_ENABLE is in progress. 38231949217328bf2357ff044f0d18677fe588c790cNick Pelly * The TASK_DISABLE triggered by airplane mode will be correctly executed 38331949217328bf2357ff044f0d18677fe588c790cNick Pelly * immediately after TASK_ENABLE is complete. This seems like the most sane 38431949217328bf2357ff044f0d18677fe588c790cNick Pelly * way to deal with these situations. 38531949217328bf2357ff044f0d18677fe588c790cNick Pelly * 38631949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 38731949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 38831949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 38931949217328bf2357ff044f0d18677fe588c790cNick Pelly * preferences 39031949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 39131949217328bf2357ff044f0d18677fe588c790cNick Pelly * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 39231949217328bf2357ff044f0d18677fe588c790cNick Pelly * process may temporarily enable the NFC adapter 39331949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 39431949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 39531949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 39631949217328bf2357ff044f0d18677fe588c790cNick Pelly protected Void doInBackground(Integer... params) { 39731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Sanity check mState 39831949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (mState) { 39931949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 40031949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 40131949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 40231949217328bf2357ff044f0d18677fe588c790cNick Pelly mState); 40331949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 40431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 40531949217328bf2357ff044f0d18677fe588c790cNick Pelly 4064467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 4074467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * override with the default. THREAD_PRIORITY_BACKGROUND causes 4084467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * us to service software I2C too slow for firmware download 4094467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * with the NXP PN544. 4104467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 4114467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly * problem only occurs on I2C platforms using PN544 4124467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly */ 4134467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 4144467dca5650a170af5020c10a8ccb25f86f1007fNick Pelly 41531949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (params[0].intValue()) { 41631949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_ENABLE: 41731949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 41831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 41931949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_DISABLE: 42031949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 42131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 42231949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_BOOT: 42331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 42431949217328bf2357ff044f0d18677fe588c790cNick Pelly !(mIsAirplaneSensitive && isAirplaneModeOn())) { 42531949217328bf2357ff044f0d18677fe588c790cNick Pelly enableInternal(); 42631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 42731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 42831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "First Boot"); 42931949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 43031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 43131949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 43231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 43331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 43431949217328bf2357ff044f0d18677fe588c790cNick Pelly case TASK_EE_WIPE: 43531949217328bf2357ff044f0d18677fe588c790cNick Pelly executeEeWipe(); 43631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 43731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 438d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly 439d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly // Restore default AsyncTask priority 440d1936808c5f37f97fdb876836194ecbfe1cdfff5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 44131949217328bf2357ff044f0d18677fe588c790cNick Pelly return null; 44231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 44331949217328bf2357ff044f0d18677fe588c790cNick Pelly 44431949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 44531949217328bf2357ff044f0d18677fe588c790cNick Pelly * Enable NFC adapter functions. 44631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 44731949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 44831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean enableInternal() { 44931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_ON) { 45031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 45131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 45231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Enabling NFC"); 45331949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_ON); 45431949217328bf2357ff044f0d18677fe588c790cNick Pelly 45531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mDeviceHost.initialize()) { 45631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Error enabling NFC"); 45731949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 45831949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 45931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 46031949217328bf2357ff044f0d18677fe588c790cNick Pelly 46131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized(NfcService.this) { 46231949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 46331949217328bf2357ff044f0d18677fe588c790cNick Pelly 46431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsZeroClickRequested) { 46531949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.enableP2p(); 46631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 46731949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_ON); 46831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 46931949217328bf2357ff044f0d18677fe588c790cNick Pelly 47031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Start polling loop */ 47131949217328bf2357ff044f0d18677fe588c790cNick Pelly applyRouting(); 47231949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 47331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 47431949217328bf2357ff044f0d18677fe588c790cNick Pelly 47531949217328bf2357ff044f0d18677fe588c790cNick Pelly /** 47631949217328bf2357ff044f0d18677fe588c790cNick Pelly * Disable all NFC adapter functions. 47731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Does not toggle preferences. 47831949217328bf2357ff044f0d18677fe588c790cNick Pelly */ 47931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean disableInternal() { 48031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mState == NfcAdapter.STATE_OFF) { 48131949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 48231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 48331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Disabling NFC"); 48431949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_TURNING_OFF); 48531949217328bf2357ff044f0d18677fe588c790cNick Pelly 48631949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 48731949217328bf2357ff044f0d18677fe588c790cNick Pelly * Implemented with a new thread (instead of a Handler or AsyncTask), 48831949217328bf2357ff044f0d18677fe588c790cNick Pelly * because the UI Thread and AsyncTask thread-pools can also get hung 48931949217328bf2357ff044f0d18677fe588c790cNick Pelly * when the NFC controller stops responding */ 49031949217328bf2357ff044f0d18677fe588c790cNick Pelly WatchDogThread watchDog = new WatchDogThread(); 49131949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.start(); 49231949217328bf2357ff044f0d18677fe588c790cNick Pelly 49331949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.disableP2p(); 49431949217328bf2357ff044f0d18677fe588c790cNick Pelly 49531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Stop watchdog if tag present 49631949217328bf2357ff044f0d18677fe588c790cNick Pelly // A convenient way to stop the watchdog properly consists of 49731949217328bf2357ff044f0d18677fe588c790cNick Pelly // disconnecting the tag. The polling loop shall be stopped before 49831949217328bf2357ff044f0d18677fe588c790cNick Pelly // to avoid the tag being discovered again. 49931949217328bf2357ff044f0d18677fe588c790cNick Pelly applyRouting(); 50031949217328bf2357ff044f0d18677fe588c790cNick Pelly maybeDisconnectTarget(); 50131949217328bf2357ff044f0d18677fe588c790cNick Pelly 50231949217328bf2357ff044f0d18677fe588c790cNick Pelly mNfcDispatcher.disableForegroundDispatch(); 50331949217328bf2357ff044f0d18677fe588c790cNick Pelly 50431949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean result = mDeviceHost.deinitialize(); 50531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 50631949217328bf2357ff044f0d18677fe588c790cNick Pelly 50731949217328bf2357ff044f0d18677fe588c790cNick Pelly watchDog.cancel(); 50831949217328bf2357ff044f0d18677fe588c790cNick Pelly 50931949217328bf2357ff044f0d18677fe588c790cNick Pelly updateState(NfcAdapter.STATE_OFF); 51031949217328bf2357ff044f0d18677fe588c790cNick Pelly 51131949217328bf2357ff044f0d18677fe588c790cNick Pelly return result; 51231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 51331949217328bf2357ff044f0d18677fe588c790cNick Pelly 51431949217328bf2357ff044f0d18677fe588c790cNick Pelly void executeEeWipe() { 51531949217328bf2357ff044f0d18677fe588c790cNick Pelly // TODO: read SE reset list from /system/etc 51631949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[][]apdus = EE_WIPE_APDUS; 51731949217328bf2357ff044f0d18677fe588c790cNick Pelly 51831949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean tempEnable = mState == NfcAdapter.STATE_OFF; 51931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 52031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!enableInternal()) { 521ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 52231949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 523f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 524f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 52531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "Executing SE wipe"); 52631949217328bf2357ff044f0d18677fe588c790cNick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 52731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (handle == 0) { 52831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Could not open the secure element"); 52931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 53031949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 53131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 53231949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 53331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 53431949217328bf2357ff044f0d18677fe588c790cNick Pelly 53531949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 53631949217328bf2357ff044f0d18677fe588c790cNick Pelly 53731949217328bf2357ff044f0d18677fe588c790cNick Pelly for (byte[] cmd : apdus) { 538ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly byte[] resp = mSecureElement.doTransceive(handle, cmd); 539ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly if (resp == null) { 540ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 541ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly break; 542ca7e72aaac66ce856c32aaffb8fd2163d7bb486aNick Pelly } 54331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 54431949217328bf2357ff044f0d18677fe588c790cNick Pelly 54531949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.resetTimeouts(); 54631949217328bf2357ff044f0d18677fe588c790cNick Pelly mSecureElement.doDisconnect(handle); 54731949217328bf2357ff044f0d18677fe588c790cNick Pelly 54831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tempEnable) { 54931949217328bf2357ff044f0d18677fe588c790cNick Pelly disableInternal(); 55031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55231949217328bf2357ff044f0d18677fe588c790cNick Pelly 55331949217328bf2357ff044f0d18677fe588c790cNick Pelly void updateState(int newState) { 55431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 55531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (newState == mState) { 55631949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 55731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 55831949217328bf2357ff044f0d18677fe588c790cNick Pelly mState = newState; 55931949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 56031949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 56131949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 56231949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(intent); 56331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 56631949217328bf2357ff044f0d18677fe588c790cNick Pelly 56731949217328bf2357ff044f0d18677fe588c790cNick Pelly void saveNfcOnSetting(boolean on) { 56831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 56931949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_NFC_ON, on); 57031949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 57131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 5720e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 5730e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 574d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen private void onFirstShare() { 575d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen Intent intent = new Intent(Settings.ACTION_NFCSHARING_SETTINGS); 576d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 577d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen PendingIntent.FLAG_UPDATE_CURRENT); 578d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen Notification notification = new Notification.Builder(mContext) 579d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .setContentTitle(mContext.getString(R.string.first_share_title)) 580d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .setContentText(mContext.getString(R.string.first_share_text)) 581d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .setContentIntent(pi) 582d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .setSmallIcon(R.drawable.stat_sys_nfc) 583d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .setAutoCancel(true) 584d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen .getNotification(); 585d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen mNotificationManager.notify(NOTIFICATION_FIRST_SHARE, notification); 586d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen } 587d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen 588d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton private void playSound(int sound) { 589d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton synchronized (this) { 590d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton mSoundPool.play(sound, 1.0f, 1.0f, 0, 0, 1.0f); 591d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 592d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 593d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 5940e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 595d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton public void onP2pBegin() { 596d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton if (!mP2pStarted) { 597d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton playSound(mStartSound); 598d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton mP2pStarted = true; 599d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 600d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 601d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 602d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton @Override 603d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton public void onP2pEnd() { 604d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton if (mP2pStarted) { 605d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton playSound(mEndSound); 606d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton mP2pStarted = false; 607d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen 608d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen // If first time, throw up a notification 609d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen if (mPrefs.getBoolean(PREF_FIRST_SHARE, true)) { 610d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen Log.i(TAG, "First NFC share"); 611d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen mPrefsEditor.putBoolean(PREF_FIRST_SHARE, false); 612d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen mPrefsEditor.apply(); 613d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen onFirstShare(); 614d11251b2d1fed7b7325c4fcb0616b2d1c654320fMartijn Coenen } 615d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 616d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 617d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 618d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton @Override 619d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton public void onP2pError() { 620d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton if (mP2pStarted) { 621d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton playSound(mErrorSound); 622d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton mP2pStarted = false; 623d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 624d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton } 625d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton 626d2d5dddf17ac2008547172cd72faa034a89d569bJeff Hamilton @Override 6272f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly public void onTerminate() { 6282f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly super.onTerminate(); 6292f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly // NFC application is persistent, it should not be destroyed by framework 6300e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly Log.wtf(TAG, "NFC service is under attack!"); 6310e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 6320e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 6334a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterService extends INfcAdapter.Stub { 634fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6350e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean enable() throws RemoteException { 63693d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6370e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 63831949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(true); 63931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 64031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "denying enable() request (airplane mode)"); 64131949217328bf2357ff044f0d18677fe588c790cNick Pelly return false; 642f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 64331949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 64431949217328bf2357ff044f0d18677fe588c790cNick Pelly 64531949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 646f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 647f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 648fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 6490e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public boolean disable() throws RemoteException { 65093d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceAdminPerm(mContext); 6510e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 65231949217328bf2357ff044f0d18677fe588c790cNick Pelly saveNfcOnSetting(false); 65331949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 65431949217328bf2357ff044f0d18677fe588c790cNick Pelly 65531949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 656f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 657f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 658fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 65931949217328bf2357ff044f0d18677fe588c790cNick Pelly public boolean isZeroClickEnabled() throws RemoteException { 66031949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 66131949217328bf2357ff044f0d18677fe588c790cNick Pelly return mIsZeroClickRequested; 66231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 663d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 664d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 665d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 666d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen public boolean enableZeroClick() throws RemoteException { 667d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 668d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 66931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsZeroClickRequested) { 67031949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 67131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 67231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "enabling 0-click"); 67331949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, true); 67431949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 67531949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsZeroClickRequested = true; 67631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 67731949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.enableP2p(); 678d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 679d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 680d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 681d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 682d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 683d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 684d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen public boolean disableZeroClick() throws RemoteException { 685d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen NfcService.enforceAdminPerm(mContext); 686d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen synchronized(NfcService.this) { 68731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsZeroClickRequested) { 68831949217328bf2357ff044f0d18677fe588c790cNick Pelly return true; 68931949217328bf2357ff044f0d18677fe588c790cNick Pelly } 69031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.i(TAG, "disabling 0-click"); 69131949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, false); 69231949217328bf2357ff044f0d18677fe588c790cNick Pelly mPrefsEditor.apply(); 69331949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsZeroClickRequested = false; 69431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isNfcEnabled()) { 69531949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.disableP2p(); 696d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 697d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 698d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen return true; 699d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 700d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen 701d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen @Override 70205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton public void enableForegroundDispatch(ComponentName activity, PendingIntent intent, 70324dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton IntentFilter[] filters, TechListParcel techListsParcel) { 704a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Permission check 70505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 706a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 707a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Argument validation 708a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (activity == null || intent == null) { 709ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton throw new IllegalArgumentException(); 710ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 711a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 712a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton // Validate the IntentFilters 713a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters != null) { 714a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filters.length == 0) { 715a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton filters = null; 716a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } else { 717a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton for (IntentFilter filter : filters) { 718a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton if (filter == null) { 719a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton throw new IllegalArgumentException("null IntentFilter"); 720a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 721a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 722a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 723a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton } 724a1935861ea244b45e29b0ec9b6f263de3c08a2d6Jeff Hamilton 72524dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton // Validate the tech lists 72624dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton String[][] techLists = null; 72724dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton if (techListsParcel != null) { 72824dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton techLists = techListsParcel.getTechLists(); 72924dbea55709219e42aa3b6b6578f29ffd447a786Jeff Hamilton } 73049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 73176a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists); 73205973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton } 73305973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton 73405973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton @Override 73505973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton public void disableForegroundDispatch(ComponentName activity) { 73605973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 73776a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly 73876a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly mNfcDispatcher.disableForegroundDispatch(); 73905973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton } 74005973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton 74105973d55daf68a286c932ee4e7ffbd6bb53789e0Jeff Hamilton @Override 742ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) { 743ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 744ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton if (activity == null || msg == null) { 745ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton throw new IllegalArgumentException(); 746ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 7472ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson if (mP2pManager.setForegroundMessage(msg)) { 748209282e9b744f3b9390154ebb69ad5587ccc2688Nick Pelly Log.w(TAG, "Replacing active NDEF push message"); 749ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 750ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 751ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 752ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 7532094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks public void enableForegroundNdefPushWithCallback(ComponentName activity, 7542094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks INdefPushCallback callback) { 7552094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7562094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks if (activity == null || callback == null) { 7572094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks throw new IllegalArgumentException(); 7582094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7592ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson if (mP2pManager.setForegroundCallback(callback)) { 760209282e9b744f3b9390154ebb69ad5587ccc2688Nick Pelly Log.w(TAG, "Replacing active NDEF push message"); 7612094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7622094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks } 7632094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks 7642094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks @Override 765ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton public void disableForegroundNdefPush(ComponentName activity) { 766ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7672ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson boolean hadMsg = mP2pManager.setForegroundMessage(null); 7682ef360deaff9f17aa72d5749ceee283cc80897afBen Dodson boolean hadCallback = mP2pManager.setForegroundCallback(null); 7692094515fca0cfa0ac87e9cc260d3953d416afe3eJason parks if (!hadMsg || !hadCallback) { 770209282e9b744f3b9390154ebb69ad5587ccc2688Nick Pelly Log.w(TAG, "No active foreground NDEF push message"); 771ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 772ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton } 773ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton 774ca1a86ecb8edce740a232c3439355e8d5b706e7aJeff Hamilton @Override 7750e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public INfcTag getNfcTagInterface() throws RemoteException { 776d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 7770e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly return mNfcTagService; 7780e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7790e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 780fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 78149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public INfcAdapterExtras getNfcAdapterExtrasInterface() { 78293d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 78349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mExtrasService; 7840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 7850bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 786fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 78731949217328bf2357ff044f0d18677fe588c790cNick Pelly public int getState() throws RemoteException { 78831949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 78931949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState; 79031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 79231949217328bf2357ff044f0d18677fe588c790cNick Pelly 79331949217328bf2357ff044f0d18677fe588c790cNick Pelly @Override 79431949217328bf2357ff044f0d18677fe588c790cNick Pelly protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 79531949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcService.this.dump(fd, pw, args); 7960e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 7970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly }; 7980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 7994a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class TagService extends INfcTag.Stub { 800fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 801f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int close(int nativeHandle) throws RemoteException { 802d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 803bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 804f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 805f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 80631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 807f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 808f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 809f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 810f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 811f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 812f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 813b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* Remove the device from the hmap */ 814b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau unregisterObject(nativeHandle); 81521545af22f9b913ec9cb124287aab2fcb0cf2b3bNick Pelly tag.disconnect(); 816b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.SUCCESS; 817f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 818f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 81949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 820f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_DISCONNECT; 821f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 822f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 823fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 824ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen public int connect(int nativeHandle, int technology) throws RemoteException { 825d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 826bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 827f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 828f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 82931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 830f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 831f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 832f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 833f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 834f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 835b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 836b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return ErrorCodes.ERROR_DISCONNECT; 837f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 838ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen 8391b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen if (technology == TagTechnology.NFC_B) { 8401b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen return ErrorCodes.ERROR_NOT_SUPPORTED; 8411b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen } 8421b1e68327701225b728d43226049ad7a5dee4bcdMartijn Coenen 843ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // Note that on most tags, all technologies are behind a single 844ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // handle. This means that the connect at the lower levels 845ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen // will do nothing, as the tag is already connected to that handle. 846ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen if (tag.connect(technology)) { 847ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.SUCCESS; 848ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } else { 849ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 850ae7d8d800ba73502d21e54d1deef16be0f061866Martijn Coenen } 851f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 852f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 853fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 854aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen public int reconnect(int nativeHandle) throws RemoteException { 855aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 856aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 857f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 858aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 859aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen // Check if NFC is enabled 86031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 861aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 862aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 863aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 864aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen /* find the tag in the hmap */ 865f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 866aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag != null) { 867aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen if (tag.reconnect()) { 868aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.SUCCESS; 869aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } else { 870aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 871aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 872aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 873aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen return ErrorCodes.ERROR_DISCONNECT; 874aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen } 875aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen 876aae427142dc22e7e419c146bc7748d9daff518e8Martijn Coenen @Override 877b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton public int[] getTechList(int nativeHandle) throws RemoteException { 878d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 879bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 880f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 88131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 882f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 883f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 884f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 885f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 886f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 887f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 888b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton return tag.getTechList(); 889f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 890f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 891f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 892f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 893fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 894f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public byte[] getUid(int nativeHandle) throws RemoteException { 895f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 896f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] uid; 897f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 898f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 89931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 900f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 901f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 902f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 903f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 904f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 905f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 906f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly uid = tag.getUid(); 907f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return uid; 908f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 909f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 910f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 911f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 912fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 913b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public boolean isPresent(int nativeHandle) throws RemoteException { 914f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 915b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 916b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau // Check if NFC is enabled 91731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 918b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 919b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 920b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 921b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau /* find the tag in the hmap */ 922f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 923b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau if (tag == null) { 924b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau return false; 925b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 926b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 927ab2b44b97936d2c5dbf6eda1245ca793e840713fMartijn Coenen return tag.isPresent(); 928b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 929b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 930fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 931f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public boolean isNdef(int nativeHandle) throws RemoteException { 932f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 933f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 934f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 93531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 9362c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 937f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 938f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 939f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 940f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 9413ba3b10867c36bff57b72ff99c7b56d63d418f3fMartijn Coenen int[] ndefInfo = new int[2]; 9422c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas if (tag == null) { 9432c3f9be8111dd454e430ffb327c051ff9d2bba21Daniel Tomas return false; 944f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 94570bbea61637e3f9eb7202efd243b9d2f9516a06aNick Pelly return tag.checkNdef(ndefInfo); 946f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 947f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 948fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9499d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 95097c6942c7c7f9df3bb8dbcc01cf7bb6e2e090005Martijn Coenen throws RemoteException { 951d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 952bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 953f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 954f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly byte[] response; 955f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 956f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 95731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 958f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 959f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 960f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 961f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 962f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 963f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 9649d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen int[] targetLost = new int[1]; 9659d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response = tag.transceive(data, raw, targetLost); 9669d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen TransceiveResult transResult = new TransceiveResult( 9679d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen (response != null) ? true : false, 9689d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen (targetLost[0] == 1) ? true : false, 9699d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen response); 9709d5511f2640903a79d24578a12a93e50a96f0c0eMartijn Coenen return transResult; 971f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 972f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 973f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 974f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 975fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 9763fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 977d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 978bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 979f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 980f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 981f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 98231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 983f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 984f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 985f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 986f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 987f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 988f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag != null) { 989f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton byte[] buf = tag.readNdef(); 990f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (buf == null) { 991f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 992f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } 993f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 994f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Create an NdefMessage */ 995f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly try { 996f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return new NdefMessage(buf); 997f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } catch (FormatException e) { 998f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 999f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1000f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1001f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return null; 1002f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1003f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1004fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10053fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1006d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1007bebaa6cc1a1eb2ce0656e17b0e09ed4747878d8eNick Pelly 1008f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 1009f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1010f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly // Check if NFC is enabled 101131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1012f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_NOT_INITIALIZED; 1013f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1014f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1015f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* find the tag in the hmap */ 1016f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 1017f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly if (tag == null) { 1018f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1019f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1020f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1021f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.writeNdef(msg.toByteArray())) { 1022f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.SUCCESS; 1023f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 1024f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly return ErrorCodes.ERROR_IO; 1025f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1026f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1027f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1028f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1029fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1030f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly public int getLastError(int nativeHandle) throws RemoteException { 1031f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton return(mDeviceHost.doGetLastError()); 1032f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1033f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1034fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10353fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 10363fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton throw new UnsupportedOperationException(); 1037f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1038f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1039fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 10403fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 104103ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 104203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1043f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 104403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 104503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen // Check if NFC is enabled 104631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 104703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 104803ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 104903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 105003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen /* find the tag in the hmap */ 1051f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 105203ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen if (tag == null) { 105303ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 105403ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 105503ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen 1056f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton if (tag.makeReadOnly()) { 105703ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.SUCCESS; 1058f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 105903ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen return ErrorCodes.ERROR_IO; 106003ee488afaa982ce934c5de399db9f9fa88c7d1eMartijn Coenen } 1061f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1062f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 10630aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen @Override 10640aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 10650aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10660aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 1067f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag; 10680aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10690aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen // Check if NFC is enabled 107031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10710aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_NOT_INITIALIZED; 10720aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10730aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10740aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen /* find the tag in the hmap */ 1075f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 10760aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag == null) { 10770aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10780aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10790aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10800aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen if (tag.formatNdef(key)) { 10810aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.SUCCESS; 1082f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton } else { 10830aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen return ErrorCodes.ERROR_IO; 10840aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10850aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen } 10860aac9419555e69512a886a6b7fa6ce2d1947c72fMartijn Coenen 10871b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 10883fb14d0868594c78a777e805545209636814e223Martijn Coenen public Tag rediscover(int nativeHandle) throws RemoteException { 10893fb14d0868594c78a777e805545209636814e223Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 10903fb14d0868594c78a777e805545209636814e223Martijn Coenen 1091f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton TagEndpoint tag = null; 10923fb14d0868594c78a777e805545209636814e223Martijn Coenen 10933fb14d0868594c78a777e805545209636814e223Martijn Coenen // Check if NFC is enabled 109431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 10953fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 10963fb14d0868594c78a777e805545209636814e223Martijn Coenen } 10973fb14d0868594c78a777e805545209636814e223Martijn Coenen 10983fb14d0868594c78a777e805545209636814e223Martijn Coenen /* find the tag in the hmap */ 1099f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tag = (TagEndpoint) findObject(nativeHandle); 11003fb14d0868594c78a777e805545209636814e223Martijn Coenen if (tag != null) { 11013fb14d0868594c78a777e805545209636814e223Martijn Coenen // For now the prime usecase for rediscover() is to be able 11023fb14d0868594c78a777e805545209636814e223Martijn Coenen // to access the NDEF technology after formatting without 11033fb14d0868594c78a777e805545209636814e223Martijn Coenen // having to remove the tag from the field, or similar 11043fb14d0868594c78a777e805545209636814e223Martijn Coenen // to have access to NdefFormatable in case low-level commands 11053fb14d0868594c78a777e805545209636814e223Martijn Coenen // were used to remove NDEF. So instead of doing a full stack 11063fb14d0868594c78a777e805545209636814e223Martijn Coenen // rediscover (which is poorly supported at the moment anyway), 11073fb14d0868594c78a777e805545209636814e223Martijn Coenen // we simply remove these two technologies and detect them 11083fb14d0868594c78a777e805545209636814e223Martijn Coenen // again. 11093fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF); 11103fb14d0868594c78a777e805545209636814e223Martijn Coenen tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1111f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton NdefMessage[] msgs = tag.findAndReadNdef(); 11123fb14d0868594c78a777e805545209636814e223Martijn Coenen // Build a new Tag object to return 11133fb14d0868594c78a777e805545209636814e223Martijn Coenen Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 11144a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton tag.getTechExtras(), tag.getHandle(), this); 11153fb14d0868594c78a777e805545209636814e223Martijn Coenen return newTag; 11163fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11173fb14d0868594c78a777e805545209636814e223Martijn Coenen return null; 11183fb14d0868594c78a777e805545209636814e223Martijn Coenen } 11193fb14d0868594c78a777e805545209636814e223Martijn Coenen 11201b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen @Override 1121fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen public int setTimeout(int tech, int timeout) throws RemoteException { 11221b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1123f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton boolean success = mDeviceHost.setTimeout(tech, timeout); 1124fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen if (success) { 1125fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.SUCCESS; 1126fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } else { 1127fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen return ErrorCodes.ERROR_INVALID_PARAM; 1128fbd90779b1525b254726eb58d07883ca74e1b21cMartijn Coenen } 1129dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen } 1130dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1131dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen @Override 1132358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen public int getTimeout(int tech) throws RemoteException { 1133358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1134358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1135358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen return mDeviceHost.getTimeout(tech); 1136358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen } 1137358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen 1138358d8b6ad611aba11e69a3b1dd9d132dbc9a7605Martijn Coenen @Override 1139dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen public void resetTimeouts() throws RemoteException { 1140dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1141dfebdbf803bf01404255f964e571056aa84173caMartijn Coenen 1142f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 11431b61f1dee91101e249b9be65d95366fa745b3b78Martijn Coenen } 11440e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly }; 1145f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1146dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException { 1147dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // Blocks until a pending open() or transceive() times out. 1148dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly //TODO: This is incorrect behavior - the close should interrupt pending 1149dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly // operations. However this is not supported by current hardware. 1150dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1151dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly synchronized(NfcService.this) { 115231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1153dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC adapter is disabled"); 1154dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1155dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (mOpenEe == null) { 1156dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new IOException("NFC EE closed"); 1157dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1158dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) { 1159dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly throw new SecurityException("Wrong PID"); 1160dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1161dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1162f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.resetTimeouts(); 1163dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mSecureElement.doDisconnect(mOpenEe.handle); 1164dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly mOpenEe = null; 1165dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 1166dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly applyRouting(); 1167dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1168dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } 1169dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly 11704a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 117149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeNoException() { 117249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 117349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", 0); 117449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 117549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 117649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private Bundle writeIoException(IOException e) { 117749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle p = new Bundle(); 117849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putInt("e", -1); 117949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly p.putString("m", e.getMessage()); 118049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return p; 118149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11820bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1183bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 118449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle open(IBinder b) throws RemoteException { 118593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 1186bd555ee64250126b60b24814120a2049943920caNick Pelly 118749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 118849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 118949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly _open(b); 119049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 119149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 119249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 11930bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 119449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 119549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 11960bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 119749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private void _open(IBinder b) throws IOException, RemoteException { 119849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 119931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 120049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC adapter is disabled"); 120149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 120249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe != null) { 120349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE already open"); 120449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 120649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly int handle = mSecureElement.doOpenSecureElementConnection(); 120749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (handle == 0) { 120849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE failed to open"); 120949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1210f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1211ba6401757f8017faeb77423f2d08fd51be1d1051Nick Pelly 121249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe = new OpenSecureElement(getCallingPid(), handle); 121349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 121449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly b.linkToDeath(mOpenEe, 0); 121549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (RemoteException e) { 121649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mOpenEe.binderDied(); 121749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 121884e1e0adc2516afd35ebab029a52e764e0490559Jason parks 121984e1e0adc2516afd35ebab029a52e764e0490559Jason parks // Add the calling package to the list of packages that have accessed 122084e1e0adc2516afd35ebab029a52e764e0490559Jason parks // the secure element. 122184e1e0adc2516afd35ebab029a52e764e0490559Jason parks for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 122284e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.add(packageName); 122384e1e0adc2516afd35ebab029a52e764e0490559Jason parks } 122449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12250bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12260bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1227bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 122849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle close() throws RemoteException { 122993d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 12300bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 123149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 123249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 1233dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly _nfcEeClose(true, getCallingPid()); 123449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 123549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 123649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12370bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 123849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 123949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12400bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1241bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 124249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public Bundle transceive(byte[] in) throws RemoteException { 124393d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 1244bd555ee64250126b60b24814120a2049943920caNick Pelly 124549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Bundle result; 124649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly byte[] out; 124749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly try { 124849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly out = _transceive(in); 124949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeNoException(); 125049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result.putByteArray("out", out); 125149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } catch (IOException e) { 125249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly result = writeIoException(e); 12530bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 125449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return result; 125549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12560bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 125749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private byte[] _transceive(byte[] data) throws IOException, RemoteException { 125849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized(NfcService.this) { 125931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 126049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC is not enabled"); 126149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 126249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (mOpenEe == null){ 126349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new IOException("NFC EE is not open"); 126449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 126549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (getCallingPid() != mOpenEe.pid) { 126649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly throw new SecurityException("Wrong PID"); 126749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 12680bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12690bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 127049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mSecureElement.doTransceive(mOpenEe.handle, data); 12710bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12720bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1273bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 127449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int getCardEmulationRoute() throws RemoteException { 127593d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 127649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly return mEeRoutingState; 12770bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 12780bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 1279bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 128049d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void setCardEmulationRoute(int route) throws RemoteException { 128193d8a69ccadfa01b0a5ec3d7edeb921a1da4bce8Jeff Hamilton NfcService.enforceNfceeAdminPerm(mContext); 128249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly mEeRoutingState = route; 128349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 12840bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 1285bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 1286bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 12875a8844da9bc569aa7289426bf7b96e7eef90abf5Nick Pelly public void authenticate(byte[] token) throws RemoteException { 1288bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks NfcService.enforceNfceeAdminPerm(mContext); 1289bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 12900bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas }; 12910bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 129249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** resources kept while secure element is open */ 129349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private class OpenSecureElement implements IBinder.DeathRecipient { 129449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int pid; // pid that opened SE 129549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public int handle; // low-level handle 129649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public OpenSecureElement(int pid, int handle) { 129749d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.pid = pid; 129849d53329a0c720a7e430220d77805bc1763545b1Nick Pelly this.handle = handle; 129949d53329a0c720a7e430220d77805bc1763545b1Nick Pelly } 1300bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks @Override 130149d53329a0c720a7e430220d77805bc1763545b1Nick Pelly public void binderDied() { 130249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly synchronized (NfcService.this) { 130349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 130449d53329a0c720a7e430220d77805bc1763545b1Nick Pelly pid = -1; 13050bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas try { 1306dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly _nfcEeClose(false, -1); 1307dfac80d25dd2816ad5af74cc4131b74134cc81b7Nick Pelly } catch (IOException e) { /* already closed */ } 13080bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13090bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13100bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas } 13110bd11735e8a28db1692f28abcc3e065abae0e8ddDaniel Tomas 131231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isNfcEnabled() { 131331949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 131431949217328bf2357ff044f0d18677fe588c790cNick Pelly return mState == NfcAdapter.STATE_ON; 1315e7a398f2f0256a4a80a4ee08b70d48dbfd8da6d2Nick Pelly } 1316aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly } 1317aa122139d77645149c09c9815fd45e7b87ce7170Nick Pelly 131831949217328bf2357ff044f0d18677fe588c790cNick Pelly class WatchDogThread extends Thread { 13192edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean mWatchDogCanceled = false; 13202edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly @Override 13212edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public void run() { 13222edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly boolean slept = false; 13232edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly while (!slept) { 13242edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly try { 13252edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Thread.sleep(10000); 13262edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly slept = true; 13272edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } catch (InterruptedException e) { } 13282edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13292edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly synchronized (this) { 13302edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly if (!mWatchDogCanceled) { 13312edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly // Trigger watch-dog 13322edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly Log.e(TAG, "Watch dog triggered"); 13332083287b83a587d8f6e9ad829ea18041dc17d842Nick Pelly mDeviceHost.doAbort(); 13342edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13352edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13362edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13372edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly public synchronized void cancel() { 13382edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly mWatchDogCanceled = true; 13392edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13402edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly } 13412edb3ee5e28ab719a3bb17b8d76b2b588405be9aNick Pelly 134249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly /** apply NFC discovery and EE routing */ 134349d53329a0c720a7e430220d77805bc1763545b1Nick Pelly private synchronized void applyRouting() { 134431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled() || mOpenEe != null) { 134531949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 134631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 134731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsScreenUnlocked) { 134831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 134931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "NFC-EE routing ON"); 135031949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.doSelectSecureElement(); 1351221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } else { 135249d53329a0c720a7e430220d77805bc1763545b1Nick Pelly Log.d(TAG, "NFC-EE routing OFF"); 1353f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton mDeviceHost.doDeselectSecureElement(); 1354221b4d6ee301fbfe19402798f7d3c11e6878c888daniel_tomas } 135531949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "NFC-C polling ON"); 135631949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.enableDiscovery(); 135731949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 135831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "NFC-EE routing OFF"); 135931949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.doDeselectSecureElement(); 136031949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "NFC-C polling OFF"); 136131949217328bf2357ff044f0d18677fe588c790cNick Pelly mDeviceHost.disableDiscovery(); 136265945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 136365945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly } 136465945ad77cadb7a3bdf171497877d2325b23def5Nick Pelly 13652436ffe91853535fad87b7a8e03d8883bae20f20Arnaud Ferir /** Disconnect any target if present */ 136631949217328bf2357ff044f0d18677fe588c790cNick Pelly void maybeDisconnectTarget() { 136731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!isNfcEnabled()) { 1368a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly return; 1369a8b7cca914e4a17f5c432f7bbeed0f1b236c55b4Nick Pelly } 137031949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectsToDisconnect; 137131949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 137231949217328bf2357ff044f0d18677fe588c790cNick Pelly Object[] objectValues = mObjectMap.values().toArray(); 137331949217328bf2357ff044f0d18677fe588c790cNick Pelly // Copy the array before we clear mObjectMap, 137431949217328bf2357ff044f0d18677fe588c790cNick Pelly // just in case the HashMap values are backed by the same array 137531949217328bf2357ff044f0d18677fe588c790cNick Pelly objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 137631949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.clear(); 137731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 137831949217328bf2357ff044f0d18677fe588c790cNick Pelly for (Object o : objectsToDisconnect) { 137931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 138031949217328bf2357ff044f0d18677fe588c790cNick Pelly if (o instanceof TagEndpoint) { 138131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from tags 138231949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) o; 138331949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 138431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (o instanceof NfcDepEndpoint) { 138531949217328bf2357ff044f0d18677fe588c790cNick Pelly // Disconnect from P2P devices 138631949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) o; 138731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 138831949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is target, request disconnection 138931949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); 139031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 139131949217328bf2357ff044f0d18677fe588c790cNick Pelly // Remote peer is initiator, we cannot disconnect 139231949217328bf2357ff044f0d18677fe588c790cNick Pelly // Just wait for field removal 1393bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1394bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1395bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1396bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1397bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks 139831949217328bf2357ff044f0d18677fe588c790cNick Pelly Object findObject(int key) { 139931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 140031949217328bf2357ff044f0d18677fe588c790cNick Pelly Object device = mObjectMap.get(key); 140131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device == null) { 140231949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "Handle not found"); 14032f8ac1e6cdeb32569bc6477d53a2d0d5608758b1Nick Pelly } 140431949217328bf2357ff044f0d18677fe588c790cNick Pelly return device; 14050e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly } 1406f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1407f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 140831949217328bf2357ff044f0d18677fe588c790cNick Pelly void registerTagObject(TagEndpoint tag) { 140931949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 141031949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(tag.getHandle(), tag); 1411f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1412b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1413b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 141431949217328bf2357ff044f0d18677fe588c790cNick Pelly void unregisterObject(int handle) { 141531949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 141631949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.remove(handle); 141731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1418f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1419f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 1420d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 14214a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 14224a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton throws IOException, LlcpException { 14234a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1424d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1425d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1426d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton /** For use by code in this process */ 14274a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 14284a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton int linearBufferLength) throws IOException, LlcpException { 14294a61d3b45e81c0070538f94747a70a49c78f12faJeff Hamilton return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1430d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton } 1431d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 143257d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton public void sendMockNdefTag(NdefMessage msg) { 1433b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton sendMessage(MSG_MOCK_NDEF, msg); 143457d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton } 143557d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 1436b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau void sendMessage(int what, Object obj) { 1437b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau Message msg = mHandler.obtainMessage(); 1438b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.what = what; 1439b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau msg.obj = obj; 1440b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau mHandler.sendMessage(msg); 1441b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1442b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 14433fb14d0868594c78a777e805545209636814e223Martijn Coenen final class NfcServiceHandler extends Handler { 1444b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau @Override 1445b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau public void handleMessage(Message msg) { 144631949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (msg.what) { 144731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_MOCK_NDEF: { 144831949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage ndefMsg = (NdefMessage) msg.obj; 144931949217328bf2357ff044f0d18677fe588c790cNick Pelly Bundle extras = new Bundle(); 145031949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 145131949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 145231949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 145331949217328bf2357ff044f0d18677fe588c790cNick Pelly extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 145431949217328bf2357ff044f0d18677fe588c790cNick Pelly Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 145531949217328bf2357ff044f0d18677fe588c790cNick Pelly new int[] { TagTechnology.NDEF }, 145631949217328bf2357ff044f0d18677fe588c790cNick Pelly new Bundle[] { extras }); 145731949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 145831949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, tag.toString()); 145931949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean delivered = mNfcDispatcher.dispatchTag(tag, 146031949217328bf2357ff044f0d18677fe588c790cNick Pelly new NdefMessage[] { ndefMsg }); 146131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (delivered) { 146231949217328bf2357ff044f0d18677fe588c790cNick Pelly onP2pEnd(); 146331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 146431949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 146531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 146657d376f1ee1a3939977b95759525585abb9601fbJeff Hamilton 146731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_NDEF_TAG: 146831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 146931949217328bf2357ff044f0d18677fe588c790cNick Pelly TagEndpoint tag = (TagEndpoint) msg.obj; 147031949217328bf2357ff044f0d18677fe588c790cNick Pelly playSound(mStartSound); 147131949217328bf2357ff044f0d18677fe588c790cNick Pelly NdefMessage[] ndefMsgs = tag.findAndReadNdef(); 1472c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 147331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (ndefMsgs != null) { 147431949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 147531949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, ndefMsgs); 147631949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 147731949217328bf2357ff044f0d18677fe588c790cNick Pelly if (tag.reconnect()) { 147831949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.startPresenceChecking(); 147931949217328bf2357ff044f0d18677fe588c790cNick Pelly dispatchTagEndpoint(tag, null); 148031949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 148131949217328bf2357ff044f0d18677fe588c790cNick Pelly tag.disconnect(); 148231949217328bf2357ff044f0d18677fe588c790cNick Pelly playSound(mErrorSound); 148331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 148431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 148531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 148631949217328bf2357ff044f0d18677fe588c790cNick Pelly 148731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_CARD_EMULATION: 148831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Emulation message"); 148931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] aid = (byte[]) msg.obj; 149031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 149131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent aidIntent = new Intent(); 149231949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.setAction(ACTION_AID_SELECTED); 149331949217328bf2357ff044f0d18677fe588c790cNick Pelly aidIntent.putExtra(EXTRA_AID, aid); 149431949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 149531949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM); 149631949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 149731949217328bf2357ff044f0d18677fe588c790cNick Pelly 149831949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_EMV_CARD_REMOVAL: 149931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Card Removal message"); 150031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 150131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent cardRemovalIntent = new Intent(); 150231949217328bf2357ff044f0d18677fe588c790cNick Pelly cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 150331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 150431949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(cardRemovalIntent, NFCEE_ADMIN_PERM); 150531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 150631949217328bf2357ff044f0d18677fe588c790cNick Pelly 150731949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_APDU_RECEIVED: 150831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "APDU Received message"); 150931949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] apduBytes = (byte[]) msg.obj; 151031949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 151131949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent apduReceivedIntent = new Intent(); 151231949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 151331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (apduBytes != null && apduBytes.length > 0) { 151431949217328bf2357ff044f0d18677fe588c790cNick Pelly apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 151531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 151631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 151731949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(apduReceivedIntent, NFCEE_ADMIN_PERM); 151831949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 151931949217328bf2357ff044f0d18677fe588c790cNick Pelly 152031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_MIFARE_ACCESS: 152131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "MIFARE access message"); 152231949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Send broadcast */ 152331949217328bf2357ff044f0d18677fe588c790cNick Pelly byte[] mifareCmd = (byte[]) msg.obj; 152431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent mifareAccessIntent = new Intent(); 152531949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 152631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mifareCmd != null && mifareCmd.length > 1) { 152731949217328bf2357ff044f0d18677fe588c790cNick Pelly int mifareBlock = mifareCmd[1] & 0xff; 152831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 152931949217328bf2357ff044f0d18677fe588c790cNick Pelly mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 153031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 153131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 153231949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(mifareAccessIntent, NFCEE_ADMIN_PERM); 153331949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 1534c9a2ae7cb238e4c72818d084cba0b05e76cba1efdaniel_tomas 153531949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_ACTIVATION: 153631949217328bf2357ff044f0d18677fe588c790cNick Pelly llcpActivated((NfcDepEndpoint) msg.obj); 153731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 153831949217328bf2357ff044f0d18677fe588c790cNick Pelly 153931949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_LLCP_LINK_DEACTIVATED: 154031949217328bf2357ff044f0d18677fe588c790cNick Pelly NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 154131949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean needsDisconnect = false; 154231949217328bf2357ff044f0d18677fe588c790cNick Pelly 154331949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 154431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 154531949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Check if the device has been already unregistered */ 154631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mObjectMap.remove(device.getHandle()) != null) { 154731949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Disconnect if we are initiator */ 154831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 154931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "disconnecting from target"); 155031949217328bf2357ff044f0d18677fe588c790cNick Pelly needsDisconnect = true; 155131949217328bf2357ff044f0d18677fe588c790cNick Pelly } else { 155231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "not disconnecting from initiator"); 155331949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155431949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (needsDisconnect) { 155731949217328bf2357ff044f0d18677fe588c790cNick Pelly device.disconnect(); // restarts polling loop 155831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 155931949217328bf2357ff044f0d18677fe588c790cNick Pelly 156031949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.onLlcpDeactivated(); 156131949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 156231949217328bf2357ff044f0d18677fe588c790cNick Pelly 156331949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_TARGET_DESELECTED: 156431949217328bf2357ff044f0d18677fe588c790cNick Pelly /* Broadcast Intent Target Deselected */ 156531949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Target Deselected"); 156631949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent intent = new Intent(); 156731949217328bf2357ff044f0d18677fe588c790cNick Pelly intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 156831949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "Broadcasting Intent"); 156931949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendOrderedBroadcast(intent, NFC_PERM); 157031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 157131949217328bf2357ff044f0d18677fe588c790cNick Pelly 157231949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_ACTIVATED: { 157331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 157431949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOnIntent = new Intent(); 157531949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 157631949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM); 157731949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 157831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 157931949217328bf2357ff044f0d18677fe588c790cNick Pelly 158031949217328bf2357ff044f0d18677fe588c790cNick Pelly case MSG_SE_FIELD_DEACTIVATED: { 158131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 158231949217328bf2357ff044f0d18677fe588c790cNick Pelly Intent eventFieldOffIntent = new Intent(); 158331949217328bf2357ff044f0d18677fe588c790cNick Pelly eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 158431949217328bf2357ff044f0d18677fe588c790cNick Pelly mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM); 158531949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 158631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 158731949217328bf2357ff044f0d18677fe588c790cNick Pelly 158831949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 158931949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.e(TAG, "Unknown message received"); 159031949217328bf2357ff044f0d18677fe588c790cNick Pelly break; 159131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1592b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau } 1593d0ec3981792e38afd119fc1c995f111f6182f6c8Jeff Hamilton 1594d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton private boolean llcpActivated(NfcDepEndpoint device) { 1595d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.d(TAG, "LLCP Activation message"); 1596d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1597d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1598d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1599d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (device.connect()) { 1600d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1601d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1602d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1603d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1604d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 160531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isZeroClickOn; 160631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 160731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 160831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1609d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 161031949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.onLlcpActivated(); 1611d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1612d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1613d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* should not happen */ 1614d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1615d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1616d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1617d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1618d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1619d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton device.disconnect(); 1620d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1621d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1622d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1623d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* 1624d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * The polling loop should have been restarted in failing 1625d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton * doConnect 1626d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton */ 1627d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1628d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1629d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1630d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Check LLCP compliancy */ 1631d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doCheckLlcp()) { 1632d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton /* Activate LLCP Link */ 1633d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (mDeviceHost.doActivateLlcp()) { 1634d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 163531949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isZeroClickOn; 163631949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (NfcService.this) { 163731949217328bf2357ff044f0d18677fe588c790cNick Pelly // Register P2P device 163831949217328bf2357ff044f0d18677fe588c790cNick Pelly mObjectMap.put(device.getHandle(), device); 1639d9567994fefe21743131adc7390acdb97f81ed67Martijn Coenen } 164031949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.onLlcpActivated(); 1641d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return true; 1642d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1643d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1644d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton Log.w(TAG, "checkLlcp failed"); 1645d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1646d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1647d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1648d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton return false; 1649d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } 1650d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton 1651f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) { 1652f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1653f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1654f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton registerTagObject(tagEndpoint); 165576a412f47ff57ce05d84fd51adbf8e72fd37a448Nick Pelly if (!mNfcDispatcher.dispatchTag(tag, msgs)) { 1656f6c56a2191d58e3f9f68e3e7d94908b04b9b66ffJeff Hamilton unregisterObject(tagEndpoint.getHandle()); 1657d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton playSound(mErrorSound); 1658d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton } else { 1659d704c298a5a1e783c71db6f39b2eef0a909b0e88Jeff Hamilton playSound(mEndSound); 16603fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 16613fb30ae5bf51d9ffe6271a345d55905dade8040dJeff Hamilton } 1662b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton } 1663b230214bcb557184cb54174889cbede53b92d54fSylvain Fonteneau 1664b74200f40f9d4f536b8782974d444f1f9178076fJeff Hamilton private NfcServiceHandler mHandler = new NfcServiceHandler(); 166549d53329a0c720a7e430220d77805bc1763545b1Nick Pelly 166631949217328bf2357ff044f0d18677fe588c790cNick Pelly class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 1667fa746bcc16d57ff12d373b9139558f5bc7164b30Jason parks @Override 1668275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks protected Void doInBackground(Boolean... params) { 1669275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]); 1670275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 1671275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (params != null && params.length > 0 && params[0]) { 1672161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly synchronized (NfcService.this) { 167331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsScreenUnlocked) { 167431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = true; 1675275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks applyRouting(); 1676275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } else { 1677275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "Ignoring enable request"); 1678275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } 1679161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 16807c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } else { 1681533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock.acquire(); 1682161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly synchronized (NfcService.this) { 168331949217328bf2357ff044f0d18677fe588c790cNick Pelly if (mIsScreenUnlocked) { 168431949217328bf2357ff044f0d18677fe588c790cNick Pelly mIsScreenUnlocked = false; 1685275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks applyRouting(); 1686275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks maybeDisconnectTarget(); 1687275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } else { 1688275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks if (DBG) Log.d(TAG, "Ignoring disable request"); 1689275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks } 1690161f84b5487ce4c1ebef9fe24ba4de00f6f756eaNick Pelly } 1691533043d1003de2f6a20a29201100d94c3c7bc9caNick Pelly mWakeLock.release(); 16927c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16937c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly return null; 16947c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16957c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly } 16967c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly 16970e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 16980e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly @Override 16990e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly public void onReceive(Context context, Intent intent) { 170031949217328bf2357ff044f0d18677fe588c790cNick Pelly String action = intent.getAction(); 170131949217328bf2357ff044f0d18677fe588c790cNick Pelly if (action.equals( 1702f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 1703ef92efa7fd86d75cc35465b84e8740f941ff0f0aJeff Hamilton if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 17040e6a0a0f50132e14d5ecad61c46e07c67fbb26fbNick Pelly 1705f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly /* Restart polling loop for notification */ 170649d53329a0c720a7e430220d77805bc1763545b1Nick Pelly applyRouting(); 1707f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly 170831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1709275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // Only enable if the screen is unlocked. If the screen is locked 1710275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // Intent.ACTION_USER_PRESENT will be broadcast when the screen is 1711275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // unlocked. 17126ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly boolean enable = !mKeyguard.isKeyguardSecure() || !mKeyguard.isKeyguardLocked(); 1713275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks 17146ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // Perform discovery enable in thread to protect against ANR when the 17156ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // NFC stack wedges. This is *not* the correct way to fix this issue - 17166ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // configuration of the local NFC adapter should be very quick and should 17176ec87aa54aad2c340c4ea0247ba4a8e0d9f10573Nick Pelly // be safe on the main thread, and the NFC stack should not wedge. 1718275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(enable); 171931949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 17207c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // Perform discovery disable in thread to protect against ANR when the 17217c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // NFC stack wedges. This is *not* the correct way to fix this issue - 17227c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // configuration of the local NFC adapter should be very quick and should 17237c034a7fe7d36b1ab039af2c44717812ea02657eNick Pelly // be safe on the main thread, and the NFC stack should not wedge. 1724275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(Boolean.FALSE); 172531949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1726275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks // The user has unlocked the screen. Enabled! 1727275fd2b59ae8a9e3eb6e77e8663aea9ca08f1159Jason parks new EnableDisableDiscoveryTask().execute(Boolean.TRUE); 172831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 172931949217328bf2357ff044f0d18677fe588c790cNick Pelly EnableDisableTask eeWipeTask = new EnableDisableTask(); 173031949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.execute(TASK_EE_WIPE); 173131949217328bf2357ff044f0d18677fe588c790cNick Pelly try { 173231949217328bf2357ff044f0d18677fe588c790cNick Pelly eeWipeTask.get(); // blocks until EE wipe is complete 173331949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (ExecutionException e) { 173431949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 173531949217328bf2357ff044f0d18677fe588c790cNick Pelly } catch (InterruptedException e) { 173631949217328bf2357ff044f0d18677fe588c790cNick Pelly Log.w(TAG, "failed to wipe NFC-EE"); 173731949217328bf2357ff044f0d18677fe588c790cNick Pelly } 173831949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 17397a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 17407a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (dataRemoved) { 17417a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton Uri data = intent.getData(); 17427a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton if (data == null) return; 17437a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton String packageName = data.getSchemeSpecificPart(); 17447a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton 17457a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton synchronized (NfcService.this) { 174684e1e0adc2516afd35ebab029a52e764e0490559Jason parks if (mSePackages.contains(packageName)) { 174731949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_EE_WIPE); 174884e1e0adc2516afd35ebab029a52e764e0490559Jason parks mSePackages.remove(packageName); 17497a7f8f8fd82936f0ee005ccfa7ac5c36760ed902Jeff Hamilton } 1750bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 1751bcd6a9954c5abafc6b14aabcc7768d0f03cc956cJason parks } 175231949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 175331949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 175431949217328bf2357ff044f0d18677fe588c790cNick Pelly // Query the airplane mode from Settings.System just to make sure that 175531949217328bf2357ff044f0d18677fe588c790cNick Pelly // some random app is not sending this intent 175631949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn != isAirplaneModeOn()) { 175731949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 175831949217328bf2357ff044f0d18677fe588c790cNick Pelly } 175931949217328bf2357ff044f0d18677fe588c790cNick Pelly if (!mIsAirplaneSensitive) { 176031949217328bf2357ff044f0d18677fe588c790cNick Pelly return; 176131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 176231949217328bf2357ff044f0d18677fe588c790cNick Pelly if (isAirplaneModeOn) { 176331949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_DISABLE); 176431949217328bf2357ff044f0d18677fe588c790cNick Pelly } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 176531949217328bf2357ff044f0d18677fe588c790cNick Pelly new EnableDisableTask().execute(TASK_ENABLE); 176631949217328bf2357ff044f0d18677fe588c790cNick Pelly } 1767f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1768f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly } 1769f067256d9556b1e01143f9ae2fd824fa5dc03138Nick Pelly }; 177031949217328bf2357ff044f0d18677fe588c790cNick Pelly 177131949217328bf2357ff044f0d18677fe588c790cNick Pelly /** Returns true if airplane mode is currently on */ 177231949217328bf2357ff044f0d18677fe588c790cNick Pelly boolean isAirplaneModeOn() { 177331949217328bf2357ff044f0d18677fe588c790cNick Pelly return Settings.System.getInt(mContext.getContentResolver(), 177431949217328bf2357ff044f0d18677fe588c790cNick Pelly Settings.System.AIRPLANE_MODE_ON, 0) == 1; 177531949217328bf2357ff044f0d18677fe588c790cNick Pelly } 177631949217328bf2357ff044f0d18677fe588c790cNick Pelly 177731949217328bf2357ff044f0d18677fe588c790cNick Pelly /** for debugging only - no il8n */ 177831949217328bf2357ff044f0d18677fe588c790cNick Pelly static String stateToString(int state) { 177931949217328bf2357ff044f0d18677fe588c790cNick Pelly switch (state) { 178031949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_OFF: 178131949217328bf2357ff044f0d18677fe588c790cNick Pelly return "off"; 178231949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_ON: 178331949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning on"; 178431949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_ON: 178531949217328bf2357ff044f0d18677fe588c790cNick Pelly return "on"; 178631949217328bf2357ff044f0d18677fe588c790cNick Pelly case NfcAdapter.STATE_TURNING_OFF: 178731949217328bf2357ff044f0d18677fe588c790cNick Pelly return "turning off"; 178831949217328bf2357ff044f0d18677fe588c790cNick Pelly default: 178931949217328bf2357ff044f0d18677fe588c790cNick Pelly return "<error>"; 179031949217328bf2357ff044f0d18677fe588c790cNick Pelly } 179131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 179231949217328bf2357ff044f0d18677fe588c790cNick Pelly 179331949217328bf2357ff044f0d18677fe588c790cNick Pelly void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 179431949217328bf2357ff044f0d18677fe588c790cNick Pelly synchronized (this) { 179531949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mState=" + stateToString(mState)); 179631949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsZeroClickRequested=" + mIsZeroClickRequested); 179731949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsScreenUnlocked=" + mIsScreenUnlocked); 179831949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 179931949217328bf2357ff044f0d18677fe588c790cNick Pelly pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 180031949217328bf2357ff044f0d18677fe588c790cNick Pelly mP2pManager.dump(fd, pw, args); 180131949217328bf2357ff044f0d18677fe588c790cNick Pelly } 180231949217328bf2357ff044f0d18677fe588c790cNick Pelly } 180374180bda362a8bc9d2f701d2c17bec0f63c20bbfBrad Fitzpatrick} 1804