PageRenderTime 86ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/src/com/android/nfc/NfcService.java

https://github.com/Cafogen/android_packages_apps_Nfc
Java | 3101 lines | 2338 code | 465 blank | 298 comment | 533 complexity | fe76b2efa156b3871c8c0abb7ef7e4b7 MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.nfc;
  17. import com.android.internal.nfc.LlcpServiceSocket;
  18. import com.android.internal.nfc.LlcpSocket;
  19. import com.android.nfc.RegisteredComponentCache.ComponentInfo;
  20. import com.android.nfc.ndefpush.NdefPushClient;
  21. import com.android.nfc.ndefpush.NdefPushServer;
  22. import com.android.nfc3.R;
  23. import android.app.Activity;
  24. import android.app.ActivityManagerNative;
  25. import android.app.Application;
  26. import android.app.IActivityManager;
  27. import android.app.PendingIntent;
  28. import android.app.PendingIntent.CanceledException;
  29. import android.app.StatusBarManager;
  30. import android.content.ActivityNotFoundException;
  31. import android.content.BroadcastReceiver;
  32. import android.content.ComponentName;
  33. import android.content.Context;
  34. import android.content.Intent;
  35. import android.content.IntentFilter;
  36. import android.content.SharedPreferences;
  37. import android.content.pm.PackageManager;
  38. import android.content.pm.ResolveInfo;
  39. import android.net.Uri;
  40. import android.nfc.ApduList;
  41. import android.nfc.ErrorCodes;
  42. import android.nfc.FormatException;
  43. import android.nfc.ILlcpConnectionlessSocket;
  44. import android.nfc.ILlcpServiceSocket;
  45. import android.nfc.ILlcpSocket;
  46. import android.nfc.INfcAdapter;
  47. import android.nfc.INfcAdapterExtras;
  48. import android.nfc.INfcTag;
  49. import android.nfc.IP2pInitiator;
  50. import android.nfc.IP2pTarget;
  51. import android.nfc.LlcpPacket;
  52. import android.nfc.NdefMessage;
  53. import android.nfc.NdefRecord;
  54. import android.nfc.NfcAdapter;
  55. import android.nfc.Tag;
  56. import android.nfc.TechListParcel;
  57. import android.nfc.TransceiveResult;
  58. import android.os.AsyncTask;
  59. import android.os.Bundle;
  60. import android.os.Handler;
  61. import android.os.IBinder;
  62. import android.os.Message;
  63. import android.os.PowerManager;
  64. import android.os.RemoteException;
  65. import android.os.ServiceManager;
  66. import android.util.Log;
  67. import java.io.ByteArrayOutputStream;
  68. import java.io.DataInputStream;
  69. import java.io.File;
  70. import java.io.FileInputStream;
  71. import java.io.FileNotFoundException;
  72. import java.io.FileOutputStream;
  73. import java.io.IOException;
  74. import java.nio.charset.Charsets;
  75. import java.util.ArrayList;
  76. import java.util.Arrays;
  77. import java.util.HashMap;
  78. import java.util.HashSet;
  79. import java.util.Iterator;
  80. import java.util.List;
  81. public class NfcService extends Application {
  82. private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
  83. static final boolean DBG = false;
  84. private static final String MY_TAG_FILE_NAME = "mytag";
  85. private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script";
  86. private static final String NFC_CONTROLLER_FIRMWARE_FILE_NAME = "/system/lib/libpn544_fw.so";
  87. static {
  88. System.loadLibrary("nfc_jni");
  89. }
  90. /**
  91. * NFC Forum "URI Record Type Definition"
  92. *
  93. * This is a mapping of "URI Identifier Codes" to URI string prefixes,
  94. * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
  95. */
  96. private static final String[] URI_PREFIX_MAP = new String[] {
  97. "", // 0x00
  98. "http://www.", // 0x01
  99. "https://www.", // 0x02
  100. "http://", // 0x03
  101. "https://", // 0x04
  102. "tel:", // 0x05
  103. "mailto:", // 0x06
  104. "ftp://anonymous:anonymous@", // 0x07
  105. "ftp://ftp.", // 0x08
  106. "ftps://", // 0x09
  107. "sftp://", // 0x0A
  108. "smb://", // 0x0B
  109. "nfs://", // 0x0C
  110. "ftp://", // 0x0D
  111. "dav://", // 0x0E
  112. "news:", // 0x0F
  113. "telnet://", // 0x10
  114. "imap:", // 0x11
  115. "rtsp://", // 0x12
  116. "urn:", // 0x13
  117. "pop:", // 0x14
  118. "sip:", // 0x15
  119. "sips:", // 0x16
  120. "tftp:", // 0x17
  121. "btspp://", // 0x18
  122. "btl2cap://", // 0x19
  123. "btgoep://", // 0x1A
  124. "tcpobex://", // 0x1B
  125. "irdaobex://", // 0x1C
  126. "file://", // 0x1D
  127. "urn:epc:id:", // 0x1E
  128. "urn:epc:tag:", // 0x1F
  129. "urn:epc:pat:", // 0x20
  130. "urn:epc:raw:", // 0x21
  131. "urn:epc:", // 0x22
  132. };
  133. public static final String SERVICE_NAME = "nfc";
  134. private static final String TAG = "NfcService";
  135. private static final String NFC_PERM = android.Manifest.permission.NFC;
  136. private static final String NFC_PERM_ERROR = "NFC permission required";
  137. private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
  138. private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
  139. private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN";
  140. private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required";
  141. private static final String PREF = "NfcServicePrefs";
  142. private static final String PREF_NFC_ON = "nfc_on";
  143. private static final boolean NFC_ON_DEFAULT = true;
  144. private static final String PREF_FIRST_BOOT = "first_boot";
  145. private static final String PREF_LLCP_LTO = "llcp_lto";
  146. private static final int LLCP_LTO_DEFAULT = 150;
  147. private static final int LLCP_LTO_MAX = 255;
  148. /** Maximum Information Unit */
  149. private static final String PREF_LLCP_MIU = "llcp_miu";
  150. private static final int LLCP_MIU_DEFAULT = 128;
  151. private static final int LLCP_MIU_MAX = 2176;
  152. /** Well Known Service List */
  153. private static final String PREF_LLCP_WKS = "llcp_wks";
  154. private static final int LLCP_WKS_DEFAULT = 1;
  155. private static final int LLCP_WKS_MAX = 15;
  156. private static final String PREF_LLCP_OPT = "llcp_opt";
  157. private static final int LLCP_OPT_DEFAULT = 0;
  158. private static final int LLCP_OPT_MAX = 3;
  159. private static final String PREF_DISCOVERY_A = "discovery_a";
  160. private static final boolean DISCOVERY_A_DEFAULT = true;
  161. private static final String PREF_DISCOVERY_B = "discovery_b";
  162. private static final boolean DISCOVERY_B_DEFAULT = true;
  163. private static final String PREF_DISCOVERY_F = "discovery_f";
  164. private static final boolean DISCOVERY_F_DEFAULT = true;
  165. private static final String PREF_DISCOVERY_15693 = "discovery_15693";
  166. private static final boolean DISCOVERY_15693_DEFAULT = true;
  167. private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip";
  168. private static final boolean DISCOVERY_NFCIP_DEFAULT = true;
  169. private static final String PREF_FIRMWARE_MODTIME = "firmware_modtime";
  170. private static final long FIRMWARE_MODTIME_DEFAULT = -1;
  171. /** NFC Reader Discovery mode for enableDiscovery() */
  172. private static final int DISCOVERY_MODE_READER = 0;
  173. private static final int PROPERTY_LLCP_LTO = 0;
  174. private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
  175. private static final int PROPERTY_LLCP_MIU = 1;
  176. private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
  177. private static final int PROPERTY_LLCP_WKS = 2;
  178. private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
  179. private static final int PROPERTY_LLCP_OPT = 3;
  180. private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
  181. private static final int PROPERTY_NFC_DISCOVERY_A = 4;
  182. private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
  183. private static final int PROPERTY_NFC_DISCOVERY_B = 5;
  184. private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
  185. private static final int PROPERTY_NFC_DISCOVERY_F = 6;
  186. private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
  187. private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
  188. private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
  189. private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
  190. private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
  191. static final int MSG_NDEF_TAG = 0;
  192. static final int MSG_CARD_EMULATION = 1;
  193. static final int MSG_LLCP_LINK_ACTIVATION = 2;
  194. static final int MSG_LLCP_LINK_DEACTIVATED = 3;
  195. static final int MSG_TARGET_DESELECTED = 4;
  196. static final int MSG_SHOW_MY_TAG_ICON = 5;
  197. static final int MSG_HIDE_MY_TAG_ICON = 6;
  198. static final int MSG_MOCK_NDEF = 7;
  199. static final int MSG_SE_FIELD_ACTIVATED = 8;
  200. static final int MSG_SE_FIELD_DEACTIVATED = 9;
  201. static final int MSG_SE_APDU_RECEIVED = 10;
  202. static final int MSG_SE_EMV_CARD_REMOVAL = 11;
  203. static final int MSG_SE_MIFARE_ACCESS = 12;
  204. static final int STATUS_CODE_TARGET_LOST = 146;
  205. // Copied from com.android.nfc_extras to avoid library dependency
  206. // Must keep in sync with com.android.nfc_extras
  207. static final int ROUTE_OFF = 1;
  208. static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
  209. public static final String ACTION_RF_FIELD_ON_DETECTED =
  210. "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
  211. public static final String ACTION_RF_FIELD_OFF_DETECTED =
  212. "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
  213. public static final String ACTION_AID_SELECTED =
  214. "com.android.nfc_extras.action.AID_SELECTED";
  215. public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
  216. public static final String ACTION_APDU_RECEIVED =
  217. "com.android.nfc_extras.action.APDU_RECEIVED";
  218. public static final String EXTRA_APDU_BYTES =
  219. "com.android.nfc_extras.extra.APDU_BYTES";
  220. public static final String ACTION_EMV_CARD_REMOVAL =
  221. "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
  222. public static final String ACTION_MIFARE_ACCESS_DETECTED =
  223. "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
  224. public static final String EXTRA_MIFARE_BLOCK =
  225. "com.android.nfc_extras.extra.MIFARE_BLOCK";
  226. // Locked on mNfcAdapter
  227. PendingIntent mDispatchOverrideIntent;
  228. IntentFilter[] mDispatchOverrideFilters;
  229. String[][] mDispatchOverrideTechLists;
  230. // TODO: none of these appear to be synchronized but are
  231. // read/written from different threads (notably Binder threads)...
  232. private int mGeneratedSocketHandle = 0;
  233. private volatile boolean mIsNfcEnabled = false;
  234. private boolean mIsDiscoveryOn = false;
  235. // NFC Execution Environment
  236. // fields below are protected by this
  237. private static final int SECURE_ELEMENT_ID = 11259375; //TODO: remove hard-coded value
  238. private NativeNfcSecureElement mSecureElement;
  239. private OpenSecureElement mOpenEe; // null when EE closed
  240. private int mEeRoutingState; // contactless interface routing
  241. // fields below are used in multiple threads and protected by synchronized(this)
  242. private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
  243. private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
  244. private boolean mScreenOn;
  245. private HashSet<String> mSePackages = new HashSet<String>();
  246. // fields below are final after onCreate()
  247. Context mContext;
  248. private NativeNfcManager mManager;
  249. private SharedPreferences mPrefs;
  250. private SharedPreferences.Editor mPrefsEditor;
  251. private PowerManager.WakeLock mWakeLock;
  252. private IActivityManager mIActivityManager;
  253. NdefPushClient mNdefPushClient;
  254. NdefPushServer mNdefPushServer;
  255. RegisteredComponentCache mTechListFilters;
  256. private static NfcService sService;
  257. public static void enforceAdminPerm(Context context) {
  258. int admin = context.checkCallingOrSelfPermission(ADMIN_PERM);
  259. int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM);
  260. if (admin != PackageManager.PERMISSION_GRANTED
  261. && nfcee != PackageManager.PERMISSION_GRANTED) {
  262. throw new SecurityException(ADMIN_PERM_ERROR);
  263. }
  264. }
  265. public static void enforceNfceeAdminPerm(Context context) {
  266. context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR);
  267. }
  268. public static NfcService getInstance() {
  269. return sService;
  270. }
  271. @Override
  272. public void onCreate() {
  273. super.onCreate();
  274. Log.i(TAG, "Starting NFC service");
  275. sService = this;
  276. mContext = this;
  277. mManager = new NativeNfcManager(mContext, this);
  278. mManager.initializeNativeStructure();
  279. mNdefPushClient = new NdefPushClient(this);
  280. mNdefPushServer = new NdefPushServer();
  281. mTechListFilters = new RegisteredComponentCache(this,
  282. NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
  283. mSecureElement = new NativeNfcSecureElement();
  284. mEeRoutingState = ROUTE_OFF;
  285. mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
  286. mPrefsEditor = mPrefs.edit();
  287. mIsNfcEnabled = false; // real preference read later
  288. PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
  289. mScreenOn = pm.isScreenOn();
  290. mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
  291. mIActivityManager = ActivityManagerNative.getDefault();
  292. ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
  293. IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
  294. filter.addAction(Intent.ACTION_SCREEN_OFF);
  295. filter.addAction(Intent.ACTION_SCREEN_ON);
  296. filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
  297. mContext.registerReceiver(mReceiver, filter);
  298. filter = new IntentFilter();
  299. filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
  300. filter.addDataScheme("package");
  301. mContext.registerReceiver(mReceiver, filter);
  302. Thread t = new Thread() {
  303. @Override
  304. public void run() {
  305. Log.d(TAG,"checking on firmware download");
  306. boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT);
  307. if (nfc_on) {
  308. Log.d(TAG,"NFC is on. Doing normal stuff");
  309. _enable(false, true);
  310. } else {
  311. Log.d(TAG,"NFC is off. Checking firmware version");
  312. _maybeUpdateFirmware();
  313. }
  314. resetSeOnFirstBoot();
  315. }
  316. };
  317. t.start();
  318. }
  319. @Override
  320. public void onTerminate() {
  321. super.onTerminate();
  322. // NFC application is persistent, it should not be destroyed by framework
  323. Log.wtf(TAG, "NFC service is under attack!");
  324. }
  325. private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() {
  326. /** Protected by "this" */
  327. NdefMessage mLocalMessage = null;
  328. @Override
  329. public boolean enable() throws RemoteException {
  330. NfcService.enforceAdminPerm(mContext);
  331. boolean isSuccess = false;
  332. boolean previouslyEnabled = isEnabled();
  333. if (!previouslyEnabled) {
  334. reset();
  335. isSuccess = _enable(previouslyEnabled, true);
  336. }
  337. return isSuccess;
  338. }
  339. @Override
  340. public boolean disable() throws RemoteException {
  341. boolean isSuccess = false;
  342. NfcService.enforceAdminPerm(mContext);
  343. boolean previouslyEnabled = isEnabled();
  344. if (DBG) Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled);
  345. if (previouslyEnabled) {
  346. isSuccess = _disable(previouslyEnabled, true);
  347. }
  348. return isSuccess;
  349. }
  350. @Override
  351. public void enableForegroundDispatch(ComponentName activity, PendingIntent intent,
  352. IntentFilter[] filters, TechListParcel techListsParcel) {
  353. // Permission check
  354. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  355. // Argument validation
  356. if (activity == null || intent == null) {
  357. throw new IllegalArgumentException();
  358. }
  359. // Validate the IntentFilters
  360. if (filters != null) {
  361. if (filters.length == 0) {
  362. filters = null;
  363. } else {
  364. for (IntentFilter filter : filters) {
  365. if (filter == null) {
  366. throw new IllegalArgumentException("null IntentFilter");
  367. }
  368. }
  369. }
  370. }
  371. // Validate the tech lists
  372. String[][] techLists = null;
  373. if (techListsParcel != null) {
  374. techLists = techListsParcel.getTechLists();
  375. }
  376. synchronized (this) {
  377. if (mDispatchOverrideIntent != null) {
  378. Log.e(TAG, "Replacing active dispatch overrides");
  379. }
  380. mDispatchOverrideIntent = intent;
  381. mDispatchOverrideFilters = filters;
  382. mDispatchOverrideTechLists = techLists;
  383. }
  384. }
  385. @Override
  386. public void disableForegroundDispatch(ComponentName activity) {
  387. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  388. synchronized (this) {
  389. if (mDispatchOverrideIntent == null) {
  390. Log.e(TAG, "No active foreground dispatching");
  391. }
  392. mDispatchOverrideIntent = null;
  393. mDispatchOverrideFilters = null;
  394. }
  395. }
  396. @Override
  397. public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) {
  398. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  399. if (activity == null || msg == null) {
  400. throw new IllegalArgumentException();
  401. }
  402. if (mNdefPushClient.setForegroundMessage(msg)) {
  403. Log.e(TAG, "Replacing active NDEF push message");
  404. }
  405. }
  406. @Override
  407. public void disableForegroundNdefPush(ComponentName activity) {
  408. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  409. if (!mNdefPushClient.setForegroundMessage(null)) {
  410. Log.e(TAG, "No active foreground NDEF push message");
  411. }
  412. }
  413. @Override
  414. public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
  415. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  416. // Check if NFC is enabled
  417. if (!mIsNfcEnabled) {
  418. return ErrorCodes.ERROR_NOT_INITIALIZED;
  419. }
  420. /* Check SAP is not already used */
  421. /* Store the socket handle */
  422. int sockeHandle = mGeneratedSocketHandle;
  423. NativeLlcpConnectionlessSocket socket;
  424. socket = mManager.doCreateLlcpConnectionlessSocket(sap);
  425. if (socket != null) {
  426. synchronized(NfcService.this) {
  427. /* update socket handle generation */
  428. mGeneratedSocketHandle++;
  429. /* Add the socket into the socket map */
  430. mSocketMap.put(mGeneratedSocketHandle, socket);
  431. return mGeneratedSocketHandle;
  432. }
  433. } else {
  434. /* Get Error Status */
  435. int errorStatus = mManager.doGetLastError();
  436. switch (errorStatus) {
  437. case ErrorCodes.ERROR_BUFFER_TO_SMALL:
  438. return ErrorCodes.ERROR_BUFFER_TO_SMALL;
  439. case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
  440. return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
  441. default:
  442. return ErrorCodes.ERROR_SOCKET_CREATION;
  443. }
  444. }
  445. }
  446. @Override
  447. public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
  448. throws RemoteException {
  449. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  450. // Check if NFC is enabled
  451. if (!mIsNfcEnabled) {
  452. return ErrorCodes.ERROR_NOT_INITIALIZED;
  453. }
  454. NativeLlcpServiceSocket socket;
  455. socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
  456. if (socket != null) {
  457. synchronized(NfcService.this) {
  458. /* update socket handle generation */
  459. mGeneratedSocketHandle++;
  460. /* Add the socket into the socket map */
  461. mSocketMap.put(mGeneratedSocketHandle, socket);
  462. return mGeneratedSocketHandle;
  463. }
  464. } else {
  465. /* Get Error Status */
  466. int errorStatus = mManager.doGetLastError();
  467. switch (errorStatus) {
  468. case ErrorCodes.ERROR_BUFFER_TO_SMALL:
  469. return ErrorCodes.ERROR_BUFFER_TO_SMALL;
  470. case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
  471. return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
  472. default:
  473. return ErrorCodes.ERROR_SOCKET_CREATION;
  474. }
  475. }
  476. }
  477. @Override
  478. public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
  479. throws RemoteException {
  480. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  481. // Check if NFC is enabled
  482. if (!mIsNfcEnabled) {
  483. return ErrorCodes.ERROR_NOT_INITIALIZED;
  484. }
  485. if (DBG) Log.d(TAG, "creating llcp socket");
  486. NativeLlcpSocket socket;
  487. socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
  488. if (socket != null) {
  489. synchronized(NfcService.this) {
  490. /* update socket handle generation */
  491. mGeneratedSocketHandle++;
  492. /* Add the socket into the socket map */
  493. mSocketMap.put(mGeneratedSocketHandle, socket);
  494. return mGeneratedSocketHandle;
  495. }
  496. } else {
  497. /* Get Error Status */
  498. int errorStatus = mManager.doGetLastError();
  499. Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus));
  500. switch (errorStatus) {
  501. case ErrorCodes.ERROR_BUFFER_TO_SMALL:
  502. return ErrorCodes.ERROR_BUFFER_TO_SMALL;
  503. case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
  504. return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
  505. default:
  506. return ErrorCodes.ERROR_SOCKET_CREATION;
  507. }
  508. }
  509. }
  510. @Override
  511. public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
  512. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  513. return mLlcpConnectionlessSocketService;
  514. }
  515. @Override
  516. public ILlcpSocket getLlcpInterface() throws RemoteException {
  517. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  518. return mLlcpSocket;
  519. }
  520. @Override
  521. public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
  522. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  523. return mLlcpServerSocketService;
  524. }
  525. @Override
  526. public INfcTag getNfcTagInterface() throws RemoteException {
  527. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  528. return mNfcTagService;
  529. }
  530. @Override
  531. public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
  532. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  533. return mP2pInitiatorService;
  534. }
  535. @Override
  536. public IP2pTarget getP2pTargetInterface() throws RemoteException {
  537. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  538. return mP2pTargetService;
  539. }
  540. @Override
  541. public INfcAdapterExtras getNfcAdapterExtrasInterface() {
  542. NfcService.enforceNfceeAdminPerm(mContext);
  543. return mExtrasService;
  544. }
  545. @Override
  546. public String getProperties(String param) throws RemoteException {
  547. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  548. if (param == null) {
  549. return null;
  550. }
  551. if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
  552. return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
  553. } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
  554. return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
  555. } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
  556. return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
  557. } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
  558. return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
  559. } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
  560. return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT));
  561. } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
  562. return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT));
  563. } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
  564. return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT));
  565. } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
  566. return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT));
  567. } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
  568. return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT));
  569. } else {
  570. return "Unknown property";
  571. }
  572. }
  573. @Override
  574. public boolean isEnabled() throws RemoteException {
  575. return mIsNfcEnabled;
  576. }
  577. @Override
  578. public int setProperties(String param, String value) throws RemoteException {
  579. NfcService.enforceAdminPerm(mContext);
  580. if (isEnabled()) {
  581. return ErrorCodes.ERROR_NFC_ON;
  582. }
  583. int val;
  584. /* Check params validity */
  585. if (param == null || value == null) {
  586. return ErrorCodes.ERROR_INVALID_PARAM;
  587. }
  588. if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
  589. val = Integer.parseInt(value);
  590. /* Check params */
  591. if (val > LLCP_LTO_MAX)
  592. return ErrorCodes.ERROR_INVALID_PARAM;
  593. /* Store value */
  594. mPrefsEditor.putInt(PREF_LLCP_LTO, val);
  595. mPrefsEditor.apply();
  596. /* Update JNI */
  597. mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
  598. } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
  599. val = Integer.parseInt(value);
  600. /* Check params */
  601. if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX))
  602. return ErrorCodes.ERROR_INVALID_PARAM;
  603. /* Store value */
  604. mPrefsEditor.putInt(PREF_LLCP_MIU, val);
  605. mPrefsEditor.apply();
  606. /* Update JNI */
  607. mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
  608. } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
  609. val = Integer.parseInt(value);
  610. /* Check params */
  611. if (val > LLCP_WKS_MAX)
  612. return ErrorCodes.ERROR_INVALID_PARAM;
  613. /* Store value */
  614. mPrefsEditor.putInt(PREF_LLCP_WKS, val);
  615. mPrefsEditor.apply();
  616. /* Update JNI */
  617. mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
  618. } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
  619. val = Integer.parseInt(value);
  620. /* Check params */
  621. if (val > LLCP_OPT_MAX)
  622. return ErrorCodes.ERROR_INVALID_PARAM;
  623. /* Store value */
  624. mPrefsEditor.putInt(PREF_LLCP_OPT, val);
  625. mPrefsEditor.apply();
  626. /* Update JNI */
  627. mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
  628. } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
  629. boolean b = Boolean.parseBoolean(value);
  630. /* Store value */
  631. mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b);
  632. mPrefsEditor.apply();
  633. /* Update JNI */
  634. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0);
  635. } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
  636. boolean b = Boolean.parseBoolean(value);
  637. /* Store value */
  638. mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b);
  639. mPrefsEditor.apply();
  640. /* Update JNI */
  641. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0);
  642. } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
  643. boolean b = Boolean.parseBoolean(value);
  644. /* Store value */
  645. mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b);
  646. mPrefsEditor.apply();
  647. /* Update JNI */
  648. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0);
  649. } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
  650. boolean b = Boolean.parseBoolean(value);
  651. /* Store value */
  652. mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b);
  653. mPrefsEditor.apply();
  654. /* Update JNI */
  655. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0);
  656. } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
  657. boolean b = Boolean.parseBoolean(value);
  658. /* Store value */
  659. mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b);
  660. mPrefsEditor.apply();
  661. /* Update JNI */
  662. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0);
  663. } else {
  664. return ErrorCodes.ERROR_INVALID_PARAM;
  665. }
  666. return ErrorCodes.SUCCESS;
  667. }
  668. @Override
  669. public NdefMessage localGet() throws RemoteException {
  670. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  671. synchronized (this) {
  672. return mLocalMessage;
  673. }
  674. }
  675. @Override
  676. public void localSet(NdefMessage message) throws RemoteException {
  677. NfcService.enforceAdminPerm(mContext);
  678. synchronized (this) {
  679. mLocalMessage = message;
  680. Context context = NfcService.this.getApplicationContext();
  681. // Send a message to the UI thread to show or hide the icon so the requests are
  682. // serialized and the icon can't get out of sync with reality.
  683. if (message != null) {
  684. FileOutputStream out = null;
  685. try {
  686. out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE);
  687. byte[] bytes = message.toByteArray();
  688. if (bytes.length == 0) {
  689. Log.w(TAG, "Setting a empty mytag");
  690. }
  691. out.write(bytes);
  692. } catch (IOException e) {
  693. Log.e(TAG, "Could not write mytag file", e);
  694. } finally {
  695. try {
  696. if (out != null) {
  697. out.flush();
  698. out.close();
  699. }
  700. } catch (IOException e) {
  701. // Ignore
  702. }
  703. }
  704. // Only show the icon if NFC is enabled.
  705. if (mIsNfcEnabled) {
  706. sendMessage(MSG_SHOW_MY_TAG_ICON, null);
  707. }
  708. } else {
  709. context.deleteFile(MY_TAG_FILE_NAME);
  710. sendMessage(MSG_HIDE_MY_TAG_ICON, null);
  711. }
  712. }
  713. }
  714. };
  715. private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
  716. private NativeLlcpSocket findSocket(int nativeHandle) {
  717. Object socket = NfcService.this.findSocket(nativeHandle);
  718. if (!(socket instanceof NativeLlcpSocket)) {
  719. return null;
  720. }
  721. return (NativeLlcpSocket) socket;
  722. }
  723. @Override
  724. public int close(int nativeHandle) throws RemoteException {
  725. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  726. NativeLlcpSocket socket = null;
  727. // Check if NFC is enabled
  728. if (!mIsNfcEnabled) {
  729. return ErrorCodes.ERROR_NOT_INITIALIZED;
  730. }
  731. /* find the socket in the hmap */
  732. socket = findSocket(nativeHandle);
  733. if (socket != null) {
  734. socket.doClose();
  735. /* Remove the socket closed from the hmap */
  736. RemoveSocket(nativeHandle);
  737. return ErrorCodes.SUCCESS;
  738. } else {
  739. return ErrorCodes.ERROR_IO;
  740. }
  741. }
  742. @Override
  743. public int connect(int nativeHandle, int sap) throws RemoteException {
  744. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  745. NativeLlcpSocket socket = null;
  746. boolean isSuccess = false;
  747. // Check if NFC is enabled
  748. if (!mIsNfcEnabled) {
  749. return ErrorCodes.ERROR_NOT_INITIALIZED;
  750. }
  751. /* find the socket in the hmap */
  752. socket = findSocket(nativeHandle);
  753. if (socket != null) {
  754. isSuccess = socket.doConnect(sap);
  755. if (isSuccess) {
  756. return ErrorCodes.SUCCESS;
  757. } else {
  758. return ErrorCodes.ERROR_IO;
  759. }
  760. } else {
  761. return ErrorCodes.ERROR_IO;
  762. }
  763. }
  764. @Override
  765. public int connectByName(int nativeHandle, String sn) throws RemoteException {
  766. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  767. NativeLlcpSocket socket = null;
  768. boolean isSuccess = false;
  769. // Check if NFC is enabled
  770. if (!mIsNfcEnabled) {
  771. return ErrorCodes.ERROR_NOT_INITIALIZED;
  772. }
  773. /* find the socket in the hmap */
  774. socket = findSocket(nativeHandle);
  775. if (socket != null) {
  776. isSuccess = socket.doConnectBy(sn);
  777. if (isSuccess) {
  778. return ErrorCodes.SUCCESS;
  779. } else {
  780. return ErrorCodes.ERROR_IO;
  781. }
  782. } else {
  783. return ErrorCodes.ERROR_IO;
  784. }
  785. }
  786. @Override
  787. public int getLocalSap(int nativeHandle) throws RemoteException {
  788. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  789. NativeLlcpSocket socket = null;
  790. // Check if NFC is enabled
  791. if (!mIsNfcEnabled) {
  792. return ErrorCodes.ERROR_NOT_INITIALIZED;
  793. }
  794. /* find the socket in the hmap */
  795. socket = findSocket(nativeHandle);
  796. if (socket != null) {
  797. return socket.getSap();
  798. } else {
  799. return 0;
  800. }
  801. }
  802. @Override
  803. public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
  804. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  805. NativeLlcpSocket socket = null;
  806. // Check if NFC is enabled
  807. if (!mIsNfcEnabled) {
  808. return ErrorCodes.ERROR_NOT_INITIALIZED;
  809. }
  810. /* find the socket in the hmap */
  811. socket = findSocket(nativeHandle);
  812. if (socket != null) {
  813. return socket.getMiu();
  814. } else {
  815. return 0;
  816. }
  817. }
  818. @Override
  819. public int getLocalSocketRw(int nativeHandle) throws RemoteException {
  820. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  821. NativeLlcpSocket socket = null;
  822. // Check if NFC is enabled
  823. if (!mIsNfcEnabled) {
  824. return ErrorCodes.ERROR_NOT_INITIALIZED;
  825. }
  826. /* find the socket in the hmap */
  827. socket = findSocket(nativeHandle);
  828. if (socket != null) {
  829. return socket.getRw();
  830. } else {
  831. return 0;
  832. }
  833. }
  834. @Override
  835. public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
  836. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  837. NativeLlcpSocket socket = null;
  838. // Check if NFC is enabled
  839. if (!mIsNfcEnabled) {
  840. return ErrorCodes.ERROR_NOT_INITIALIZED;
  841. }
  842. /* find the socket in the hmap */
  843. socket = findSocket(nativeHandle);
  844. if (socket != null) {
  845. if (socket.doGetRemoteSocketMiu() != 0) {
  846. return socket.doGetRemoteSocketMiu();
  847. } else {
  848. return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
  849. }
  850. } else {
  851. return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
  852. }
  853. }
  854. @Override
  855. public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
  856. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  857. NativeLlcpSocket socket = null;
  858. // Check if NFC is enabled
  859. if (!mIsNfcEnabled) {
  860. return ErrorCodes.ERROR_NOT_INITIALIZED;
  861. }
  862. /* find the socket in the hmap */
  863. socket = findSocket(nativeHandle);
  864. if (socket != null) {
  865. if (socket.doGetRemoteSocketRw() != 0) {
  866. return socket.doGetRemoteSocketRw();
  867. } else {
  868. return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
  869. }
  870. } else {
  871. return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
  872. }
  873. }
  874. @Override
  875. public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
  876. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  877. NativeLlcpSocket socket = null;
  878. // Check if NFC is enabled
  879. if (!mIsNfcEnabled) {
  880. return ErrorCodes.ERROR_NOT_INITIALIZED;
  881. }
  882. /* find the socket in the hmap */
  883. socket = findSocket(nativeHandle);
  884. if (socket != null) {
  885. return socket.doReceive(receiveBuffer);
  886. } else {
  887. return 0;
  888. }
  889. }
  890. @Override
  891. public int send(int nativeHandle, byte[] data) throws RemoteException {
  892. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  893. NativeLlcpSocket socket = null;
  894. boolean isSuccess = false;
  895. // Check if NFC is enabled
  896. if (!mIsNfcEnabled) {
  897. return ErrorCodes.ERROR_NOT_INITIALIZED;
  898. }
  899. /* find the socket in the hmap */
  900. socket = findSocket(nativeHandle);
  901. if (socket != null) {
  902. isSuccess = socket.doSend(data);
  903. if (isSuccess) {
  904. return ErrorCodes.SUCCESS;
  905. } else {
  906. return ErrorCodes.ERROR_IO;
  907. }
  908. } else {
  909. return ErrorCodes.ERROR_IO;
  910. }
  911. }
  912. };
  913. private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
  914. private NativeLlcpServiceSocket findSocket(int nativeHandle) {
  915. Object socket = NfcService.this.findSocket(nativeHandle);
  916. if (!(socket instanceof NativeLlcpServiceSocket)) {
  917. return null;
  918. }
  919. return (NativeLlcpServiceSocket) socket;
  920. }
  921. @Override
  922. public int accept(int nativeHandle) throws RemoteException {
  923. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  924. NativeLlcpServiceSocket socket = null;
  925. NativeLlcpSocket clientSocket = null;
  926. // Check if NFC is enabled
  927. if (!mIsNfcEnabled) {
  928. return ErrorCodes.ERROR_NOT_INITIALIZED;
  929. }
  930. /* find the socket in the hmap */
  931. socket = findSocket(nativeHandle);
  932. if (socket != null) {
  933. clientSocket = socket.doAccept(socket.getMiu(),
  934. socket.getRw(), socket.getLinearBufferLength());
  935. if (clientSocket != null) {
  936. /* Add the socket into the socket map */
  937. synchronized(this) {
  938. mGeneratedSocketHandle++;
  939. mSocketMap.put(mGeneratedSocketHandle, clientSocket);
  940. return mGeneratedSocketHandle;
  941. }
  942. } else {
  943. return ErrorCodes.ERROR_IO;
  944. }
  945. } else {
  946. return ErrorCodes.ERROR_IO;
  947. }
  948. }
  949. @Override
  950. public void close(int nativeHandle) throws RemoteException {
  951. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  952. NativeLlcpServiceSocket socket = null;
  953. // Check if NFC is enabled
  954. if (!mIsNfcEnabled) {
  955. return;
  956. }
  957. /* find the socket in the hmap */
  958. socket = findSocket(nativeHandle);
  959. if (socket != null) {
  960. socket.doClose();
  961. synchronized (this) {
  962. /* Remove the socket closed from the hmap */
  963. RemoveSocket(nativeHandle);
  964. }
  965. }
  966. }
  967. };
  968. private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
  969. private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) {
  970. Object socket = NfcService.this.findSocket(nativeHandle);
  971. if (!(socket instanceof NativeLlcpConnectionlessSocket)) {
  972. return null;
  973. }
  974. return (NativeLlcpConnectionlessSocket) socket;
  975. }
  976. @Override
  977. public void close(int nativeHandle) throws RemoteException {
  978. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  979. NativeLlcpConnectionlessSocket socket = null;
  980. // Check if NFC is enabled
  981. if (!mIsNfcEnabled) {
  982. return;
  983. }
  984. /* find the socket in the hmap */
  985. socket = findSocket(nativeHandle);
  986. if (socket != null) {
  987. socket.doClose();
  988. /* Remove the socket closed from the hmap */
  989. RemoveSocket(nativeHandle);
  990. }
  991. }
  992. @Override
  993. public int getSap(int nativeHandle) throws RemoteException {
  994. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  995. NativeLlcpConnectionlessSocket socket = null;
  996. // Check if NFC is enabled
  997. if (!mIsNfcEnabled) {
  998. return ErrorCodes.ERROR_NOT_INITIALIZED;
  999. }
  1000. /* find the socket in the hmap */
  1001. socket = findSocket(nativeHandle);
  1002. if (socket != null) {
  1003. return socket.getSap();
  1004. } else {
  1005. return 0;
  1006. }
  1007. }
  1008. @Override
  1009. public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
  1010. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1011. NativeLlcpConnectionlessSocket socket = null;
  1012. LlcpPacket packet;
  1013. // Check if NFC is enabled
  1014. if (!mIsNfcEnabled) {
  1015. return null;
  1016. }
  1017. /* find the socket in the hmap */
  1018. socket = findSocket(nativeHandle);
  1019. if (socket != null) {
  1020. packet = socket.doReceiveFrom(socket.getLinkMiu());
  1021. if (packet != null) {
  1022. return packet;
  1023. }
  1024. return null;
  1025. } else {
  1026. return null;
  1027. }
  1028. }
  1029. @Override
  1030. public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
  1031. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1032. NativeLlcpConnectionlessSocket socket = null;
  1033. boolean isSuccess = false;
  1034. // Check if NFC is enabled
  1035. if (!mIsNfcEnabled) {
  1036. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1037. }
  1038. /* find the socket in the hmap */
  1039. socket = findSocket(nativeHandle);
  1040. if (socket != null) {
  1041. isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
  1042. if (isSuccess) {
  1043. return ErrorCodes.SUCCESS;
  1044. } else {
  1045. return ErrorCodes.ERROR_IO;
  1046. }
  1047. } else {
  1048. return ErrorCodes.ERROR_IO;
  1049. }
  1050. }
  1051. };
  1052. private final INfcTag mNfcTagService = new INfcTag.Stub() {
  1053. @Override
  1054. public int close(int nativeHandle) throws RemoteException {
  1055. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1056. NativeNfcTag tag = null;
  1057. // Check if NFC is enabled
  1058. if (!mIsNfcEnabled) {
  1059. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1060. }
  1061. /* find the tag in the hmap */
  1062. tag = (NativeNfcTag) findObject(nativeHandle);
  1063. if (tag != null) {
  1064. /* Remove the device from the hmap */
  1065. unregisterObject(nativeHandle);
  1066. tag.disconnect();
  1067. return ErrorCodes.SUCCESS;
  1068. }
  1069. /* Restart polling loop for notification */
  1070. applyRouting();
  1071. return ErrorCodes.ERROR_DISCONNECT;
  1072. }
  1073. @Override
  1074. public int connect(int nativeHandle, int technology) throws RemoteException {
  1075. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1076. NativeNfcTag tag = null;
  1077. // Check if NFC is enabled
  1078. if (!mIsNfcEnabled) {
  1079. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1080. }
  1081. /* find the tag in the hmap */
  1082. tag = (NativeNfcTag) findObject(nativeHandle);
  1083. if (tag == null) {
  1084. return ErrorCodes.ERROR_DISCONNECT;
  1085. }
  1086. // Note that on most tags, all technologies are behind a single
  1087. // handle. This means that the connect at the lower levels
  1088. // will do nothing, as the tag is already connected to that handle.
  1089. if (tag.connect(technology) == 0) {
  1090. return ErrorCodes.SUCCESS;
  1091. } else {
  1092. return ErrorCodes.ERROR_DISCONNECT;
  1093. }
  1094. }
  1095. @Override
  1096. public int reconnect(int nativeHandle) throws RemoteException {
  1097. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1098. NativeNfcTag tag = null;
  1099. // Check if NFC is enabled
  1100. if (!mIsNfcEnabled) {
  1101. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1102. }
  1103. /* find the tag in the hmap */
  1104. tag = (NativeNfcTag) findObject(nativeHandle);
  1105. if (tag != null) {
  1106. if (tag.reconnect() == 0) {
  1107. return ErrorCodes.SUCCESS;
  1108. } else {
  1109. return ErrorCodes.ERROR_DISCONNECT;
  1110. }
  1111. }
  1112. return ErrorCodes.ERROR_DISCONNECT;
  1113. }
  1114. @Override
  1115. public int[] getTechList(int nativeHandle) throws RemoteException {
  1116. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1117. // Check if NFC is enabled
  1118. if (!mIsNfcEnabled) {
  1119. return null;
  1120. }
  1121. /* find the tag in the hmap */
  1122. NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle);
  1123. if (tag != null) {
  1124. return tag.getTechList();
  1125. }
  1126. return null;
  1127. }
  1128. @Override
  1129. public byte[] getUid(int nativeHandle) throws RemoteException {
  1130. NativeNfcTag tag = null;
  1131. byte[] uid;
  1132. // Check if NFC is enabled
  1133. if (!mIsNfcEnabled) {
  1134. return null;
  1135. }
  1136. /* find the tag in the hmap */
  1137. tag = (NativeNfcTag) findObject(nativeHandle);
  1138. if (tag != null) {
  1139. uid = tag.getUid();
  1140. return uid;
  1141. }
  1142. return null;
  1143. }
  1144. @Override
  1145. public boolean isPresent(int nativeHandle) throws RemoteException {
  1146. NativeNfcTag tag = null;
  1147. // Check if NFC is enabled
  1148. if (!mIsNfcEnabled) {
  1149. return false;
  1150. }
  1151. /* find the tag in the hmap */
  1152. tag = (NativeNfcTag) findObject(nativeHandle);
  1153. if (tag == null) {
  1154. return false;
  1155. }
  1156. return tag.isPresent();
  1157. }
  1158. @Override
  1159. public boolean isNdef(int nativeHandle) throws RemoteException {
  1160. NativeNfcTag tag = null;
  1161. // Check if NFC is enabled
  1162. if (!mIsNfcEnabled) {
  1163. return false;
  1164. }
  1165. /* find the tag in the hmap */
  1166. tag = (NativeNfcTag) findObject(nativeHandle);
  1167. int[] ndefInfo = new int[2];
  1168. if (tag == null) {
  1169. return false;
  1170. }
  1171. return tag.checkNdef(ndefInfo) == 0;
  1172. }
  1173. @Override
  1174. public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
  1175. throws RemoteException {
  1176. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1177. NativeNfcTag tag = null;
  1178. byte[] response;
  1179. // Check if NFC is enabled
  1180. if (!mIsNfcEnabled) {
  1181. return null;
  1182. }
  1183. /* find the tag in the hmap */
  1184. tag = (NativeNfcTag) findObject(nativeHandle);
  1185. if (tag != null) {
  1186. int[] targetLost = new int[1];
  1187. response = tag.transceive(data, raw, targetLost);
  1188. TransceiveResult transResult = new TransceiveResult(
  1189. (response != null) ? true : false,
  1190. (targetLost[0] == 1) ? true : false,
  1191. response);
  1192. return transResult;
  1193. }
  1194. return null;
  1195. }
  1196. @Override
  1197. public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
  1198. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1199. NativeNfcTag tag;
  1200. // Check if NFC is enabled
  1201. if (!mIsNfcEnabled) {
  1202. return null;
  1203. }
  1204. /* find the tag in the hmap */
  1205. tag = (NativeNfcTag) findObject(nativeHandle);
  1206. if (tag != null) {
  1207. byte[] buf = tag.read();
  1208. if (buf == null)
  1209. return null;
  1210. /* Create an NdefMessage */
  1211. try {
  1212. return new NdefMessage(buf);
  1213. } catch (FormatException e) {
  1214. return null;
  1215. }
  1216. }
  1217. return null;
  1218. }
  1219. @Override
  1220. public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
  1221. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1222. NativeNfcTag tag;
  1223. // Check if NFC is enabled
  1224. if (!mIsNfcEnabled) {
  1225. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1226. }
  1227. /* find the tag in the hmap */
  1228. tag = (NativeNfcTag) findObject(nativeHandle);
  1229. if (tag == null) {
  1230. return ErrorCodes.ERROR_IO;
  1231. }
  1232. if (tag.write(msg.toByteArray())) {
  1233. return ErrorCodes.SUCCESS;
  1234. }
  1235. else {
  1236. return ErrorCodes.ERROR_IO;
  1237. }
  1238. }
  1239. @Override
  1240. public int getLastError(int nativeHandle) throws RemoteException {
  1241. return(mManager.doGetLastError());
  1242. }
  1243. @Override
  1244. public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
  1245. throw new UnsupportedOperationException();
  1246. }
  1247. @Override
  1248. public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
  1249. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1250. NativeNfcTag tag;
  1251. // Check if NFC is enabled
  1252. if (!mIsNfcEnabled) {
  1253. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1254. }
  1255. /* find the tag in the hmap */
  1256. tag = (NativeNfcTag) findObject(nativeHandle);
  1257. if (tag == null) {
  1258. return ErrorCodes.ERROR_IO;
  1259. }
  1260. if (tag.makeReadonly()) {
  1261. return ErrorCodes.SUCCESS;
  1262. }
  1263. else {
  1264. return ErrorCodes.ERROR_IO;
  1265. }
  1266. }
  1267. @Override
  1268. public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
  1269. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1270. NativeNfcTag tag;
  1271. // Check if NFC is enabled
  1272. if (!mIsNfcEnabled) {
  1273. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1274. }
  1275. /* find the tag in the hmap */
  1276. tag = (NativeNfcTag) findObject(nativeHandle);
  1277. if (tag == null) {
  1278. return ErrorCodes.ERROR_IO;
  1279. }
  1280. if (tag.formatNdef(key)) {
  1281. return ErrorCodes.SUCCESS;
  1282. }
  1283. else {
  1284. return ErrorCodes.ERROR_IO;
  1285. }
  1286. }
  1287. @Override
  1288. public void setIsoDepTimeout(int timeout) throws RemoteException {
  1289. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1290. mManager.setIsoDepTimeout(timeout);
  1291. }
  1292. @Override
  1293. public void resetIsoDepTimeout() throws RemoteException {
  1294. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1295. mManager.resetIsoDepTimeout();
  1296. }
  1297. };
  1298. private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
  1299. @Override
  1300. public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
  1301. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1302. NativeP2pDevice device;
  1303. // Check if NFC is enabled
  1304. if (!mIsNfcEnabled) {
  1305. return null;
  1306. }
  1307. /* find the device in the hmap */
  1308. device = (NativeP2pDevice) findObject(nativeHandle);
  1309. if (device != null) {
  1310. byte[] buff = device.getGeneralBytes();
  1311. if (buff == null)
  1312. return null;
  1313. return buff;
  1314. }
  1315. return null;
  1316. }
  1317. @Override
  1318. public int getMode(int nativeHandle) throws RemoteException {
  1319. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1320. NativeP2pDevice device;
  1321. // Check if NFC is enabled
  1322. if (!mIsNfcEnabled) {
  1323. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1324. }
  1325. /* find the device in the hmap */
  1326. device = (NativeP2pDevice) findObject(nativeHandle);
  1327. if (device != null) {
  1328. return device.getMode();
  1329. }
  1330. return ErrorCodes.ERROR_INVALID_PARAM;
  1331. }
  1332. @Override
  1333. public byte[] receive(int nativeHandle) throws RemoteException {
  1334. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1335. NativeP2pDevice device;
  1336. // Check if NFC is enabled
  1337. if (!mIsNfcEnabled) {
  1338. return null;
  1339. }
  1340. /* find the device in the hmap */
  1341. device = (NativeP2pDevice) findObject(nativeHandle);
  1342. if (device != null) {
  1343. byte[] buff = device.doReceive();
  1344. if (buff == null)
  1345. return null;
  1346. return buff;
  1347. }
  1348. /* Restart polling loop for notification */
  1349. applyRouting();
  1350. return null;
  1351. }
  1352. @Override
  1353. public boolean send(int nativeHandle, byte[] data) throws RemoteException {
  1354. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1355. NativeP2pDevice device;
  1356. boolean isSuccess = false;
  1357. // Check if NFC is enabled
  1358. if (!mIsNfcEnabled) {
  1359. return isSuccess;
  1360. }
  1361. /* find the device in the hmap */
  1362. device = (NativeP2pDevice) findObject(nativeHandle);
  1363. if (device != null) {
  1364. isSuccess = device.doSend(data);
  1365. }
  1366. return isSuccess;
  1367. }
  1368. };
  1369. private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
  1370. @Override
  1371. public int connect(int nativeHandle) throws RemoteException {
  1372. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1373. NativeP2pDevice device;
  1374. // Check if NFC is enabled
  1375. if (!mIsNfcEnabled) {
  1376. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1377. }
  1378. /* find the device in the hmap */
  1379. device = (NativeP2pDevice) findObject(nativeHandle);
  1380. if (device != null) {
  1381. if (device.doConnect()) {
  1382. return ErrorCodes.SUCCESS;
  1383. }
  1384. }
  1385. return ErrorCodes.ERROR_CONNECT;
  1386. }
  1387. @Override
  1388. public boolean disconnect(int nativeHandle) throws RemoteException {
  1389. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1390. NativeP2pDevice device;
  1391. boolean isSuccess = false;
  1392. // Check if NFC is enabled
  1393. if (!mIsNfcEnabled) {
  1394. return isSuccess;
  1395. }
  1396. /* find the device in the hmap */
  1397. device = (NativeP2pDevice) findObject(nativeHandle);
  1398. if (device != null) {
  1399. if (isSuccess = device.doDisconnect()) {
  1400. /* remove the device from the hmap */
  1401. unregisterObject(nativeHandle);
  1402. /* Restart polling loop for notification */
  1403. applyRouting();
  1404. }
  1405. }
  1406. return isSuccess;
  1407. }
  1408. @Override
  1409. public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
  1410. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1411. NativeP2pDevice device;
  1412. // Check if NFC is enabled
  1413. if (!mIsNfcEnabled) {
  1414. return null;
  1415. }
  1416. /* find the device in the hmap */
  1417. device = (NativeP2pDevice) findObject(nativeHandle);
  1418. if (device != null) {
  1419. byte[] buff = device.getGeneralBytes();
  1420. if (buff == null)
  1421. return null;
  1422. return buff;
  1423. }
  1424. return null;
  1425. }
  1426. @Override
  1427. public int getMode(int nativeHandle) throws RemoteException {
  1428. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1429. NativeP2pDevice device;
  1430. // Check if NFC is enabled
  1431. if (!mIsNfcEnabled) {
  1432. return ErrorCodes.ERROR_NOT_INITIALIZED;
  1433. }
  1434. /* find the device in the hmap */
  1435. device = (NativeP2pDevice) findObject(nativeHandle);
  1436. if (device != null) {
  1437. return device.getMode();
  1438. }
  1439. return ErrorCodes.ERROR_INVALID_PARAM;
  1440. }
  1441. @Override
  1442. public byte[] transceive(int nativeHandle, byte[] data)
  1443. throws RemoteException {
  1444. mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
  1445. NativeP2pDevice device;
  1446. // Check if NFC is enabled
  1447. if (!mIsNfcEnabled) {
  1448. return null;
  1449. }
  1450. /* find the device in the hmap */
  1451. device = (NativeP2pDevice) findObject(nativeHandle);
  1452. if (device != null) {
  1453. byte[] buff = device.doTransceive(data);
  1454. if (buff == null)
  1455. return null;
  1456. return buff;
  1457. }
  1458. return null;
  1459. }
  1460. };
  1461. private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException {
  1462. // Blocks until a pending open() or transceive() times out.
  1463. //TODO: This is incorrect behavior - the close should interrupt pending
  1464. // operations. However this is not supported by current hardware.
  1465. synchronized(NfcService.this) {
  1466. if (!mIsNfcEnabled) {
  1467. throw new IOException("NFC adapter is disabled");
  1468. }
  1469. if (mOpenEe == null) {
  1470. throw new IOException("NFC EE closed");
  1471. }
  1472. if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) {
  1473. throw new SecurityException("Wrong PID");
  1474. }
  1475. mManager.doResetIsoDepTimeout();
  1476. mSecureElement.doDisconnect(mOpenEe.handle);
  1477. mOpenEe = null;
  1478. applyRouting();
  1479. }
  1480. }
  1481. private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() {
  1482. private Bundle writeNoException() {
  1483. Bundle p = new Bundle();
  1484. p.putInt("e", 0);
  1485. return p;
  1486. }
  1487. private Bundle writeIoException(IOException e) {
  1488. Bundle p = new Bundle();
  1489. p.putInt("e", -1);
  1490. p.putString("m", e.getMessage());
  1491. return p;
  1492. }
  1493. @Override
  1494. public Bundle open(IBinder b) throws RemoteException {
  1495. NfcService.enforceNfceeAdminPerm(mContext);
  1496. Bundle result;
  1497. try {
  1498. _open(b);
  1499. result = writeNoException();
  1500. } catch (IOException e) {
  1501. result = writeIoException(e);
  1502. }
  1503. return result;
  1504. }
  1505. private void _open(IBinder b) throws IOException, RemoteException {
  1506. synchronized(NfcService.this) {
  1507. if (!mIsNfcEnabled) {
  1508. throw new IOException("NFC adapter is disabled");
  1509. }
  1510. if (mOpenEe != null) {
  1511. throw new IOException("NFC EE already open");
  1512. }
  1513. int handle = mSecureElement.doOpenSecureElementConnection();
  1514. if (handle == 0) {
  1515. throw new IOException("NFC EE failed to open");
  1516. }
  1517. mManager.doSetIsoDepTimeout(10000);
  1518. mOpenEe = new OpenSecureElement(getCallingPid(), handle);
  1519. try {
  1520. b.linkToDeath(mOpenEe, 0);
  1521. } catch (RemoteException e) {
  1522. mOpenEe.binderDied();
  1523. }
  1524. // Add the calling package to the list of packages that have accessed
  1525. // the secure element.
  1526. for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) {
  1527. mSePackages.add(packageName);
  1528. }
  1529. }
  1530. }
  1531. @Override
  1532. public Bundle close() throws RemoteException {
  1533. NfcService.enforceNfceeAdminPerm(mContext);
  1534. Bundle result;
  1535. try {
  1536. _nfcEeClose(true, getCallingPid());
  1537. result = writeNoException();
  1538. } catch (IOException e) {
  1539. result = writeIoException(e);
  1540. }
  1541. return result;
  1542. }
  1543. @Override
  1544. public Bundle transceive(byte[] in) throws RemoteException {
  1545. NfcService.enforceNfceeAdminPerm(mContext);
  1546. Bundle result;
  1547. byte[] out;
  1548. try {
  1549. out = _transceive(in);
  1550. result = writeNoException();
  1551. result.putByteArray("out", out);
  1552. } catch (IOException e) {
  1553. result = writeIoException(e);
  1554. }
  1555. return result;
  1556. }
  1557. private byte[] _transceive(byte[] data) throws IOException, RemoteException {
  1558. synchronized(NfcService.this) {
  1559. if (!mIsNfcEnabled) {
  1560. throw new IOException("NFC is not enabled");
  1561. }
  1562. if (mOpenEe == null){
  1563. throw new IOException("NFC EE is not open");
  1564. }
  1565. if (getCallingPid() != mOpenEe.pid) {
  1566. throw new SecurityException("Wrong PID");
  1567. }
  1568. }
  1569. return mSecureElement.doTransceive(mOpenEe.handle, data);
  1570. }
  1571. @Override
  1572. public int getCardEmulationRoute() throws RemoteException {
  1573. NfcService.enforceNfceeAdminPerm(mContext);
  1574. return mEeRoutingState;
  1575. }
  1576. @Override
  1577. public void setCardEmulationRoute(int route) throws RemoteException {
  1578. NfcService.enforceNfceeAdminPerm(mContext);
  1579. mEeRoutingState = route;
  1580. applyRouting();
  1581. }
  1582. @Override
  1583. public void authenticate(byte[] token) throws RemoteException {
  1584. NfcService.enforceNfceeAdminPerm(mContext);
  1585. }
  1586. };
  1587. /** resources kept while secure element is open */
  1588. private class OpenSecureElement implements IBinder.DeathRecipient {
  1589. public int pid; // pid that opened SE
  1590. public int handle; // low-level handle
  1591. public OpenSecureElement(int pid, int handle) {
  1592. this.pid = pid;
  1593. this.handle = handle;
  1594. }
  1595. @Override
  1596. public void binderDied() {
  1597. synchronized (NfcService.this) {
  1598. if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
  1599. pid = -1;
  1600. try {
  1601. _nfcEeClose(false, -1);
  1602. } catch (IOException e) { /* already closed */ }
  1603. }
  1604. }
  1605. }
  1606. private boolean _enable(boolean oldEnabledState, boolean savePref) {
  1607. applyProperties();
  1608. boolean isSuccess = mManager.initialize();
  1609. if (isSuccess) {
  1610. mIsNfcEnabled = true;
  1611. mIsDiscoveryOn = true;
  1612. /* Start polling loop */
  1613. applyRouting();
  1614. /* bring up the my tag server */
  1615. mNdefPushServer.start();
  1616. } else {
  1617. Log.w(TAG, "Error enabling NFC");
  1618. mIsNfcEnabled = false;
  1619. }
  1620. if (savePref) {
  1621. updateNfcOnSetting(oldEnabledState);
  1622. }
  1623. return isSuccess;
  1624. }
  1625. private boolean _disable(boolean oldEnabledState, boolean savePref) {
  1626. /* sometimes mManager.deinitialize() hangs, watch-dog it */
  1627. WatchDogThread watchDog = new WatchDogThread();
  1628. watchDog.start();
  1629. boolean isSuccess;
  1630. /* tear down the my tag server */
  1631. mNdefPushServer.stop();
  1632. // Stop watchdog if tag present
  1633. // A convenient way to stop the watchdog properly consists of
  1634. // disconnecting the tag. The polling loop shall be stopped before
  1635. // to avoid the tag being discovered again.
  1636. mIsDiscoveryOn = false;
  1637. applyRouting();
  1638. maybeDisconnectTarget();
  1639. isSuccess = mManager.deinitialize();
  1640. if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess);
  1641. if (isSuccess) {
  1642. mIsNfcEnabled = false;
  1643. // Clear out any old dispatch overrides and NDEF push message
  1644. synchronized (this) {
  1645. mDispatchOverrideFilters = null;
  1646. mDispatchOverrideIntent = null;
  1647. }
  1648. mNdefPushClient.setForegroundMessage(null);
  1649. }
  1650. if (savePref) {
  1651. updateNfcOnSetting(oldEnabledState);
  1652. }
  1653. watchDog.cancel();
  1654. return isSuccess;
  1655. }
  1656. // Check that the NFC controller firmware is up to date. This
  1657. // ensures that firmware updates are applied in a timely fashion,
  1658. // and makes it much less likely that the user will have to wait
  1659. // for a firmware download when they enable NFC in the settings
  1660. // app. Firmware download can take some time, so this should be
  1661. // run in a separate thread.
  1662. private void _maybeUpdateFirmware() {
  1663. // check the timestamp of the firmware file
  1664. File firmwareFile;
  1665. int nbRetry = 0;
  1666. try {
  1667. firmwareFile = new File(NFC_CONTROLLER_FIRMWARE_FILE_NAME);
  1668. } catch(NullPointerException npe) {
  1669. Log.e(TAG,"path to firmware file was null");
  1670. return;
  1671. }
  1672. long modtime = firmwareFile.lastModified();
  1673. long prev_fw_modtime = mPrefs.getLong(PREF_FIRMWARE_MODTIME, FIRMWARE_MODTIME_DEFAULT);
  1674. Log.d(TAG,"prev modtime: " + prev_fw_modtime);
  1675. Log.d(TAG,"new modtime: " + modtime);
  1676. if (prev_fw_modtime == modtime) {
  1677. return;
  1678. }
  1679. // FW download.
  1680. while(nbRetry < 5) {
  1681. Log.d(TAG,"Perform Download");
  1682. if(mManager.doDownload()) {
  1683. Log.d(TAG,"Download Success");
  1684. // Now that we've finished updating the firmware, save the new modtime.
  1685. mPrefsEditor.putLong(PREF_FIRMWARE_MODTIME, modtime);
  1686. mPrefsEditor.apply();
  1687. break;
  1688. } else {
  1689. Log.d(TAG,"Download Failed");
  1690. nbRetry++;
  1691. }
  1692. }
  1693. }
  1694. private class WatchDogThread extends Thread {
  1695. boolean mWatchDogCanceled = false;
  1696. @Override
  1697. public void run() {
  1698. boolean slept = false;
  1699. while (!slept) {
  1700. try {
  1701. Thread.sleep(10000);
  1702. slept = true;
  1703. } catch (InterruptedException e) { }
  1704. }
  1705. synchronized (this) {
  1706. if (!mWatchDogCanceled) {
  1707. // Trigger watch-dog
  1708. Log.e(TAG, "Watch dog triggered");
  1709. mManager.doAbort();
  1710. }
  1711. }
  1712. }
  1713. public synchronized void cancel() {
  1714. mWatchDogCanceled = true;
  1715. }
  1716. }
  1717. /** apply NFC discovery and EE routing */
  1718. private synchronized void applyRouting() {
  1719. if (mIsNfcEnabled && mOpenEe == null) {
  1720. if (mScreenOn) {
  1721. if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
  1722. Log.d(TAG, "NFC-EE routing ON");
  1723. mManager.doSelectSecureElement(SECURE_ELEMENT_ID);
  1724. } else {
  1725. Log.d(TAG, "NFC-EE routing OFF");
  1726. mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
  1727. }
  1728. if (mIsDiscoveryOn) {
  1729. Log.d(TAG, "NFC-C discovery ON");
  1730. mManager.enableDiscovery(DISCOVERY_MODE_READER);
  1731. } else {
  1732. Log.d(TAG, "NFC-C discovery OFF");
  1733. mManager.disableDiscovery();
  1734. }
  1735. } else {
  1736. Log.d(TAG, "NFC-EE routing OFF");
  1737. mManager.doDeselectSecureElement(SECURE_ELEMENT_ID);
  1738. Log.d(TAG, "NFC-C discovery OFF");
  1739. mManager.disableDiscovery();
  1740. }
  1741. }
  1742. }
  1743. /** Disconnect any target if present */
  1744. private synchronized void maybeDisconnectTarget() {
  1745. if (mIsNfcEnabled) {
  1746. Iterator<?> iterator = mObjectMap.values().iterator();
  1747. while(iterator.hasNext()) {
  1748. Object object = iterator.next();
  1749. if(object instanceof NativeNfcTag) {
  1750. // Disconnect from tags
  1751. NativeNfcTag tag = (NativeNfcTag) object;
  1752. tag.disconnect();
  1753. }
  1754. else if(object instanceof NativeP2pDevice) {
  1755. // Disconnect from P2P devices
  1756. NativeP2pDevice device = (NativeP2pDevice) object;
  1757. if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
  1758. // Remote peer is target, request disconnection
  1759. device.doDisconnect();
  1760. }
  1761. else {
  1762. // Remote peer is initiator, we cannot disconnect
  1763. // Just wait for field removal
  1764. }
  1765. }
  1766. iterator.remove();
  1767. }
  1768. }
  1769. }
  1770. //TODO: dont hardcode this
  1771. private static final byte[][] SE_RESET_APDUS = {
  1772. {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
  1773. {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
  1774. {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
  1775. {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
  1776. {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
  1777. {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
  1778. {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
  1779. };
  1780. private void resetSeOnFirstBoot() {
  1781. if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
  1782. Log.i(TAG, "First Boot");
  1783. mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
  1784. mPrefsEditor.apply();
  1785. executeSeReset();
  1786. }
  1787. }
  1788. private synchronized void executeSeReset() {
  1789. // TODO: read SE reset list from /system/etc
  1790. //List<byte[]> apdus = readSeResetApdus();
  1791. byte[][]apdus = SE_RESET_APDUS;
  1792. if (apdus == null) {
  1793. return;
  1794. }
  1795. boolean tempEnable = !mIsNfcEnabled;
  1796. if (tempEnable) {
  1797. if (!_enable(false, false)) {
  1798. Log.w(TAG, "Could not enable NFC to reset EE!");
  1799. return;
  1800. }
  1801. }
  1802. Log.i(TAG, "Executing SE Reset Script");
  1803. int handle = mSecureElement.doOpenSecureElementConnection();
  1804. if (handle == 0) {
  1805. Log.e(TAG, "Could not open the secure element!");
  1806. if (tempEnable) {
  1807. _disable(true, false);
  1808. }
  1809. return;
  1810. }
  1811. mManager.doSetIsoDepTimeout(10000);
  1812. for (byte[] cmd : apdus) {
  1813. mSecureElement.doTransceive(handle, cmd);
  1814. }
  1815. mManager.doResetIsoDepTimeout();
  1816. mSecureElement.doDisconnect(handle);
  1817. if (tempEnable) {
  1818. _disable(true, false);
  1819. }
  1820. }
  1821. private List<byte[]> readSeResetApdus() {
  1822. FileInputStream input = null;
  1823. List<byte[]> apdus = null;
  1824. try {
  1825. input = openFileInput(SE_RESET_SCRIPT_FILE_NAME);
  1826. DataInputStream stream = new DataInputStream(input);
  1827. int commandsSize = stream.readInt();
  1828. apdus = new ArrayList<byte[]>(commandsSize);
  1829. for (int i = 0 ; i < commandsSize ; i++) {
  1830. int length = stream.readInt();
  1831. byte[] cmd = new byte[length];
  1832. stream.read(cmd);
  1833. apdus.add(cmd);
  1834. }
  1835. return apdus;
  1836. } catch (FileNotFoundException e) {
  1837. Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME);
  1838. } catch (IOException e) {
  1839. Log.e(TAG, "SE Reset Script corrupt: ", e);
  1840. apdus = null;
  1841. } finally {
  1842. try {
  1843. if (input != null) {
  1844. input.close();
  1845. }
  1846. } catch (IOException e) {
  1847. // Ignore
  1848. }
  1849. }
  1850. return apdus;
  1851. }
  1852. private void applyProperties() {
  1853. mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT));
  1854. mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT));
  1855. mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT));
  1856. mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT));
  1857. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A,
  1858. mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0);
  1859. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B,
  1860. mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0);
  1861. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F,
  1862. mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0);
  1863. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693,
  1864. mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0);
  1865. mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP,
  1866. mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0);
  1867. }
  1868. private void updateNfcOnSetting(boolean oldEnabledState) {
  1869. mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled);
  1870. mPrefsEditor.apply();
  1871. synchronized(this) {
  1872. if (oldEnabledState != mIsNfcEnabled) {
  1873. Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE);
  1874. intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
  1875. intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled);
  1876. mContext.sendBroadcast(intent);
  1877. }
  1878. if (mIsNfcEnabled) {
  1879. Context context = getApplicationContext();
  1880. // Set this to null by default. If there isn't a tag on disk
  1881. // or if there was an error reading the tag then this will cause
  1882. // the status bar icon to be removed.
  1883. NdefMessage myTag = null;
  1884. FileInputStream input = null;
  1885. try {
  1886. input = context.openFileInput(MY_TAG_FILE_NAME);
  1887. ByteArrayOutputStream bytes = new ByteArrayOutputStream();
  1888. byte[] buffer = new byte[4096];
  1889. int read = 0;
  1890. while ((read = input.read(buffer)) > 0) {
  1891. bytes.write(buffer, 0, read);
  1892. }
  1893. myTag = new NdefMessage(bytes.toByteArray());
  1894. } catch (FileNotFoundException e) {
  1895. // Ignore.
  1896. } catch (IOException e) {
  1897. Log.e(TAG, "Could not read mytag file: ", e);
  1898. context.deleteFile(MY_TAG_FILE_NAME);
  1899. } catch (FormatException e) {
  1900. Log.e(TAG, "Invalid NdefMessage for mytag", e);
  1901. context.deleteFile(MY_TAG_FILE_NAME);
  1902. } finally {
  1903. try {
  1904. if (input != null) {
  1905. input.close();
  1906. }
  1907. } catch (IOException e) {
  1908. // Ignore
  1909. }
  1910. }
  1911. try {
  1912. mNfcAdapter.localSet(myTag);
  1913. } catch (RemoteException e) {
  1914. // Ignore
  1915. }
  1916. } else {
  1917. sendMessage(MSG_HIDE_MY_TAG_ICON, null);
  1918. }
  1919. }
  1920. }
  1921. // Reset all internals
  1922. private synchronized void reset() {
  1923. // TODO: none of these appear to be synchronized but are
  1924. // read/written from different threads (notably Binder threads)...
  1925. // Clear tables
  1926. mObjectMap.clear();
  1927. mSocketMap.clear();
  1928. // Reset variables
  1929. mIsNfcEnabled = false;
  1930. }
  1931. private synchronized Object findObject(int key) {
  1932. Object device = null;
  1933. device = mObjectMap.get(key);
  1934. if (device == null) {
  1935. Log.w(TAG, "Handle not found !");
  1936. }
  1937. return device;
  1938. }
  1939. synchronized void registerTagObject(NativeNfcTag nativeTag) {
  1940. mObjectMap.put(nativeTag.getHandle(), nativeTag);
  1941. }
  1942. synchronized void unregisterObject(int handle) {
  1943. mObjectMap.remove(handle);
  1944. }
  1945. private synchronized Object findSocket(int key) {
  1946. if (mSocketMap == null) {
  1947. return null;
  1948. }
  1949. return mSocketMap.get(key);
  1950. }
  1951. private void RemoveSocket(int key) {
  1952. mSocketMap.remove(key);
  1953. }
  1954. /** For use by code in this process */
  1955. public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) {
  1956. try {
  1957. int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength);
  1958. if (ErrorCodes.isError(handle)) {
  1959. Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
  1960. return null;
  1961. }
  1962. return new LlcpSocket(mLlcpSocket, handle);
  1963. } catch (RemoteException e) {
  1964. // This will never happen since the code is calling into it's own process
  1965. throw new IllegalStateException("unable to talk to myself", e);
  1966. }
  1967. }
  1968. /** For use by code in this process */
  1969. public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
  1970. int linearBufferLength) {
  1971. try {
  1972. int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
  1973. if (ErrorCodes.isError(handle)) {
  1974. Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle));
  1975. return null;
  1976. }
  1977. return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle);
  1978. } catch (RemoteException e) {
  1979. // This will never happen since the code is calling into it's own process
  1980. throw new IllegalStateException("unable to talk to myself", e);
  1981. }
  1982. }
  1983. private void activateLlcpLink() {
  1984. /* Broadcast Intent Link LLCP activated */
  1985. Intent LlcpLinkIntent = new Intent();
  1986. LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
  1987. LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
  1988. NfcAdapter.LLCP_LINK_STATE_ACTIVATED);
  1989. if (DBG) Log.d(TAG, "Broadcasting LLCP activation");
  1990. mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
  1991. }
  1992. public void sendMockNdefTag(NdefMessage msg) {
  1993. sendMessage(MSG_MOCK_NDEF, msg);
  1994. }
  1995. void sendMessage(int what, Object obj) {
  1996. Message msg = mHandler.obtainMessage();
  1997. msg.what = what;
  1998. msg.obj = obj;
  1999. mHandler.sendMessage(msg);
  2000. }
  2001. final class NfcServiceHandler extends Handler {
  2002. public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) {
  2003. // Try to find NDEF on any of the technologies.
  2004. int[] technologies = nativeTag.getTechList();
  2005. int[] handles = nativeTag.getHandleList();
  2006. int techIndex = 0;
  2007. int lastHandleScanned = 0;
  2008. boolean ndefFoundAndConnected = false;
  2009. boolean isTargetLost = false;
  2010. NdefMessage[] ndefMsgs = null;
  2011. boolean foundFormattable = false;
  2012. int formattableHandle = 0;
  2013. int formattableTechnology = 0;
  2014. int status;
  2015. while ((!ndefFoundAndConnected) && (techIndex < technologies.length) && (!isTargetLost))
  2016. {
  2017. if (handles[techIndex] != lastHandleScanned) {
  2018. // We haven't seen this handle yet, connect and checkndef
  2019. status = nativeTag.connect(technologies[techIndex]);
  2020. if (status == 0) {
  2021. // Check if this type is NDEF formatable
  2022. if (!foundFormattable) {
  2023. if (nativeTag.isNdefFormatable()) {
  2024. foundFormattable = true;
  2025. formattableHandle = nativeTag.getConnectedHandle();
  2026. formattableTechnology = nativeTag.getConnectedTechnology();
  2027. // We'll only add formattable tech if no ndef is
  2028. // found - this is because libNFC refuses to format
  2029. // an already NDEF formatted tag.
  2030. }
  2031. nativeTag.reconnect();
  2032. } // else, already found formattable technology
  2033. int[] ndefinfo = new int[2];
  2034. status = nativeTag.checkNdef(ndefinfo);
  2035. if (status == 0) {
  2036. ndefFoundAndConnected = true;
  2037. boolean generateEmptyNdef = false;
  2038. int supportedNdefLength = ndefinfo[0];
  2039. int cardState = ndefinfo[1];
  2040. byte[] buff = nativeTag.read();
  2041. if (buff != null) {
  2042. ndefMsgs = new NdefMessage[1];
  2043. try {
  2044. ndefMsgs[0] = new NdefMessage(buff);
  2045. nativeTag.addNdefTechnology(ndefMsgs[0],
  2046. nativeTag.getConnectedHandle(),
  2047. nativeTag.getConnectedLibNfcType(),
  2048. nativeTag.getConnectedTechnology(),
  2049. supportedNdefLength, cardState);
  2050. nativeTag.reconnect();
  2051. } catch (FormatException e) {
  2052. // Create an intent anyway, without NDEF messages
  2053. generateEmptyNdef = true;
  2054. }
  2055. } else {
  2056. generateEmptyNdef = true;
  2057. }
  2058. if (generateEmptyNdef) {
  2059. ndefMsgs = new NdefMessage[] { };
  2060. nativeTag.addNdefTechnology(null,
  2061. nativeTag.getConnectedHandle(),
  2062. nativeTag.getConnectedLibNfcType(),
  2063. nativeTag.getConnectedTechnology(),
  2064. supportedNdefLength, cardState);
  2065. nativeTag.reconnect();
  2066. }
  2067. } else { // else, no NDEF on this tech, continue loop
  2068. Log.d(TAG, "Check NDEF Failed - status = "+ status);
  2069. if (status == STATUS_CODE_TARGET_LOST) {
  2070. isTargetLost = true;
  2071. }
  2072. }
  2073. } else {
  2074. Log.d(TAG, "Connect Failed - status = "+ status);
  2075. if (status == STATUS_CODE_TARGET_LOST) {
  2076. isTargetLost = true;
  2077. }
  2078. }
  2079. }
  2080. lastHandleScanned = handles[techIndex];
  2081. techIndex++;
  2082. }
  2083. if (ndefMsgs == null && foundFormattable) {
  2084. // Tag is not NDEF yet, and found a formattable target,
  2085. // so add formattable tech to tech list.
  2086. nativeTag.addNdefFormatableTechnology(
  2087. formattableHandle,
  2088. formattableTechnology);
  2089. }
  2090. return ndefMsgs;
  2091. }
  2092. @Override
  2093. public void handleMessage(Message msg) {
  2094. switch (msg.what) {
  2095. case MSG_MOCK_NDEF: {
  2096. NdefMessage ndefMsg = (NdefMessage) msg.obj;
  2097. Tag tag = Tag.createMockTag(new byte[] { 0x00 },
  2098. new int[] { },
  2099. new Bundle[] { });
  2100. Log.d(TAG, "mock NDEF tag, starting corresponding activity");
  2101. Log.d(TAG, tag.toString());
  2102. dispatchTag(tag, new NdefMessage[] { ndefMsg });
  2103. break;
  2104. }
  2105. case MSG_NDEF_TAG:
  2106. if (DBG) Log.d(TAG, "Tag detected, notifying applications");
  2107. NativeNfcTag nativeTag = (NativeNfcTag) msg.obj;
  2108. NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag);
  2109. if (ndefMsgs != null) {
  2110. nativeTag.startPresenceChecking();
  2111. dispatchNativeTag(nativeTag, ndefMsgs);
  2112. } else {
  2113. // No ndef found or connect failed, just try to reconnect and dispatch
  2114. if (nativeTag.getLastStatusCode() != STATUS_CODE_TARGET_LOST) {
  2115. if (nativeTag.reconnect() == 0) {
  2116. nativeTag.startPresenceChecking();
  2117. dispatchNativeTag(nativeTag, null);
  2118. }
  2119. } else {
  2120. nativeTag.disconnect();
  2121. }
  2122. }
  2123. break;
  2124. case MSG_CARD_EMULATION:
  2125. if (DBG) Log.d(TAG, "Card Emulation message");
  2126. byte[] aid = (byte[]) msg.obj;
  2127. /* Send broadcast */
  2128. Intent aidIntent = new Intent();
  2129. aidIntent.setAction(ACTION_AID_SELECTED);
  2130. aidIntent.putExtra(EXTRA_AID, aid);
  2131. if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED);
  2132. mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM);
  2133. break;
  2134. case MSG_SE_EMV_CARD_REMOVAL:
  2135. if (DBG) Log.d(TAG, "Card Removal message");
  2136. /* Send broadcast */
  2137. Intent cardRemovalIntent = new Intent();
  2138. cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL);
  2139. if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL);
  2140. mContext.sendBroadcast(cardRemovalIntent, NFCEE_ADMIN_PERM);
  2141. break;
  2142. case MSG_SE_APDU_RECEIVED:
  2143. if (DBG) Log.d(TAG, "APDU Received message");
  2144. byte[] apduBytes = (byte[]) msg.obj;
  2145. /* Send broadcast */
  2146. Intent apduReceivedIntent = new Intent();
  2147. apduReceivedIntent.setAction(ACTION_APDU_RECEIVED);
  2148. if (apduBytes != null && apduBytes.length > 0) {
  2149. apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes);
  2150. }
  2151. if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED);
  2152. mContext.sendBroadcast(apduReceivedIntent, NFCEE_ADMIN_PERM);
  2153. break;
  2154. case MSG_SE_MIFARE_ACCESS:
  2155. if (DBG) Log.d(TAG, "MIFARE access message");
  2156. /* Send broadcast */
  2157. byte[] mifareCmd = (byte[]) msg.obj;
  2158. Intent mifareAccessIntent = new Intent();
  2159. mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED);
  2160. if (mifareCmd != null && mifareCmd.length > 1) {
  2161. int mifareBlock = mifareCmd[1] & 0xff;
  2162. if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock);
  2163. mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock);
  2164. }
  2165. if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED);
  2166. mContext.sendBroadcast(mifareAccessIntent, NFCEE_ADMIN_PERM);
  2167. break;
  2168. case MSG_LLCP_LINK_ACTIVATION:
  2169. NativeP2pDevice device = (NativeP2pDevice) msg.obj;
  2170. Log.d(TAG, "LLCP Activation message");
  2171. if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
  2172. if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
  2173. if (device.doConnect()) {
  2174. /* Check Llcp compliancy */
  2175. if (mManager.doCheckLlcp()) {
  2176. /* Activate Llcp Link */
  2177. if (mManager.doActivateLlcp()) {
  2178. if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
  2179. // Register P2P device
  2180. mObjectMap.put(device.getHandle(), device);
  2181. activateLlcpLink();
  2182. } else {
  2183. /* should not happen */
  2184. Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect.");
  2185. device.doDisconnect();
  2186. }
  2187. } else {
  2188. if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
  2189. device.doDisconnect();
  2190. }
  2191. } else {
  2192. if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted...");
  2193. /* The polling loop should have been restarted in failing doConnect */
  2194. }
  2195. } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
  2196. if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
  2197. /* Check Llcp compliancy */
  2198. if (mManager.doCheckLlcp()) {
  2199. /* Activate Llcp Link */
  2200. if (mManager.doActivateLlcp()) {
  2201. if (DBG) Log.d(TAG, "Target Activate LLCP OK");
  2202. // Register P2P device
  2203. mObjectMap.put(device.getHandle(), device);
  2204. activateLlcpLink();
  2205. }
  2206. } else {
  2207. Log.w(TAG, "checkLlcp failed");
  2208. }
  2209. }
  2210. break;
  2211. case MSG_LLCP_LINK_DEACTIVATED:
  2212. device = (NativeP2pDevice) msg.obj;
  2213. Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
  2214. synchronized (NfcService.this) {
  2215. /* Check if the device has been already unregistered */
  2216. if (mObjectMap.remove(device.getHandle()) != null) {
  2217. /* Disconnect if we are initiator */
  2218. if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
  2219. if (DBG) Log.d(TAG, "disconnecting from target");
  2220. /* Restart polling loop */
  2221. device.doDisconnect();
  2222. } else {
  2223. if (DBG) Log.d(TAG, "not disconnecting from initiator");
  2224. }
  2225. }
  2226. }
  2227. /* Broadcast Intent Link LLCP activated */
  2228. Intent LlcpLinkIntent = new Intent();
  2229. LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED);
  2230. LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED,
  2231. NfcAdapter.LLCP_LINK_STATE_DEACTIVATED);
  2232. if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation");
  2233. mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM);
  2234. break;
  2235. case MSG_TARGET_DESELECTED:
  2236. /* Broadcast Intent Target Deselected */
  2237. if (DBG) Log.d(TAG, "Target Deselected");
  2238. Intent TargetDeselectedIntent = new Intent();
  2239. TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION);
  2240. if (DBG) Log.d(TAG, "Broadcasting Intent");
  2241. mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM);
  2242. break;
  2243. case MSG_SHOW_MY_TAG_ICON: {
  2244. StatusBarManager sb = (StatusBarManager) getSystemService(
  2245. Context.STATUS_BAR_SERVICE);
  2246. sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0);
  2247. break;
  2248. }
  2249. case MSG_HIDE_MY_TAG_ICON: {
  2250. StatusBarManager sb = (StatusBarManager) getSystemService(
  2251. Context.STATUS_BAR_SERVICE);
  2252. sb.removeIcon("nfc");
  2253. break;
  2254. }
  2255. case MSG_SE_FIELD_ACTIVATED:{
  2256. if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
  2257. Intent eventFieldOnIntent = new Intent();
  2258. eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
  2259. if (DBG) Log.d(TAG, "Broadcasting Intent");
  2260. mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM);
  2261. break;
  2262. }
  2263. case MSG_SE_FIELD_DEACTIVATED:{
  2264. if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
  2265. Intent eventFieldOffIntent = new Intent();
  2266. eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
  2267. if (DBG) Log.d(TAG, "Broadcasting Intent");
  2268. mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM);
  2269. break;
  2270. }
  2271. default:
  2272. Log.e(TAG, "Unknown message received");
  2273. break;
  2274. }
  2275. }
  2276. private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) {
  2277. Intent intent = new Intent(action);
  2278. intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
  2279. intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
  2280. intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs);
  2281. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  2282. return intent;
  2283. }
  2284. private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) {
  2285. Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(),
  2286. nativeTag.getTechExtras(), nativeTag.getHandle(), mNfcTagService);
  2287. registerTagObject(nativeTag);
  2288. if (!dispatchTag(tag, msgs)) {
  2289. unregisterObject(nativeTag.getHandle());
  2290. nativeTag.disconnect();
  2291. }
  2292. }
  2293. public byte[] concat(byte[]... arrays) {
  2294. int length = 0;
  2295. for (byte[] array : arrays) {
  2296. length += array.length;
  2297. }
  2298. byte[] result = new byte[length];
  2299. int pos = 0;
  2300. for (byte[] array : arrays) {
  2301. System.arraycopy(array, 0, result, pos, array.length);
  2302. pos += array.length;
  2303. }
  2304. return result;
  2305. }
  2306. private Uri parseWellKnownUriRecord(NdefRecord record) {
  2307. byte[] payload = record.getPayload();
  2308. /*
  2309. * payload[0] contains the URI Identifier Code, per the
  2310. * NFC Forum "URI Record Type Definition" section 3.2.2.
  2311. *
  2312. * payload[1]...payload[payload.length - 1] contains the rest of
  2313. * the URI.
  2314. */
  2315. String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)];
  2316. byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
  2317. Arrays.copyOfRange(payload, 1, payload.length));
  2318. return Uri.parse(new String(fullUri, Charsets.UTF_8));
  2319. }
  2320. private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) {
  2321. short tnf = record.getTnf();
  2322. byte[] type = record.getType();
  2323. try {
  2324. switch (tnf) {
  2325. case NdefRecord.TNF_MIME_MEDIA: {
  2326. intent.setType(new String(type, Charsets.US_ASCII));
  2327. return true;
  2328. }
  2329. case NdefRecord.TNF_ABSOLUTE_URI: {
  2330. intent.setData(Uri.parse(new String(type, Charsets.UTF_8)));
  2331. return true;
  2332. }
  2333. case NdefRecord.TNF_WELL_KNOWN: {
  2334. byte[] payload = record.getPayload();
  2335. if (payload == null || payload.length == 0) return false;
  2336. if (Arrays.equals(type, NdefRecord.RTD_TEXT)) {
  2337. intent.setType("text/plain");
  2338. return true;
  2339. } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) {
  2340. // Parse the smart poster looking for the URI
  2341. try {
  2342. NdefMessage msg = new NdefMessage(record.getPayload());
  2343. for (NdefRecord subRecord : msg.getRecords()) {
  2344. short subTnf = subRecord.getTnf();
  2345. if (subTnf == NdefRecord.TNF_WELL_KNOWN
  2346. && Arrays.equals(subRecord.getType(),
  2347. NdefRecord.RTD_URI)) {
  2348. intent.setData(parseWellKnownUriRecord(subRecord));
  2349. return true;
  2350. } else if (subTnf == NdefRecord.TNF_ABSOLUTE_URI) {
  2351. intent.setData(Uri.parse(new String(subRecord.getType(),
  2352. Charsets.UTF_8)));
  2353. return true;
  2354. }
  2355. }
  2356. } catch (FormatException e) {
  2357. return false;
  2358. }
  2359. } else if (Arrays.equals(type, NdefRecord.RTD_URI)) {
  2360. intent.setData(parseWellKnownUriRecord(record));
  2361. return true;
  2362. }
  2363. return false;
  2364. }
  2365. case NdefRecord.TNF_EXTERNAL_TYPE: {
  2366. intent.setData(Uri.parse("vnd.android.nfc://ext/" +
  2367. new String(record.getType(), Charsets.US_ASCII)));
  2368. return true;
  2369. }
  2370. }
  2371. return false;
  2372. } catch (Exception e) {
  2373. Log.e(TAG, "failed to parse record", e);
  2374. return false;
  2375. }
  2376. }
  2377. /** Returns false if no activities were found to dispatch to */
  2378. private boolean dispatchTag(Tag tag, NdefMessage[] msgs) {
  2379. if (DBG) {
  2380. Log.d(TAG, "Dispatching tag");
  2381. Log.d(TAG, tag.toString());
  2382. }
  2383. IntentFilter[] overrideFilters;
  2384. PendingIntent overrideIntent;
  2385. String[][] overrideTechLists;
  2386. boolean foregroundNdefPush = mNdefPushClient.getForegroundMessage() != null;
  2387. synchronized (mNfcAdapter) {
  2388. overrideFilters = mDispatchOverrideFilters;
  2389. overrideIntent = mDispatchOverrideIntent;
  2390. overrideTechLists = mDispatchOverrideTechLists;
  2391. }
  2392. // First look for dispatch overrides
  2393. if (overrideIntent != null) {
  2394. if (DBG) Log.d(TAG, "Attempting to dispatch tag with override");
  2395. try {
  2396. if (dispatchTagInternal(tag, msgs, overrideIntent, overrideFilters,
  2397. overrideTechLists)) {
  2398. if (DBG) Log.d(TAG, "Dispatched to override");
  2399. return true;
  2400. }
  2401. Log.w(TAG, "Dispatch override registered, but no filters matched");
  2402. } catch (CanceledException e) {
  2403. Log.w(TAG, "Dispatch overrides pending intent was canceled");
  2404. synchronized (mNfcAdapter) {
  2405. mDispatchOverrideFilters = null;
  2406. mDispatchOverrideIntent = null;
  2407. mDispatchOverrideTechLists = null;
  2408. }
  2409. }
  2410. }
  2411. // If there is not foreground NDEF push setup try a normal dispatch.
  2412. //
  2413. // This is avoided when disabled in the NDEF push case to avoid the situation where each
  2414. // user has a different app in the foreground, causing each to launch itself on the
  2415. // remote device and the apps swapping which is in the foreground on each phone.
  2416. if (!foregroundNdefPush) {
  2417. try {
  2418. return dispatchTagInternal(tag, msgs, null, null, null);
  2419. } catch (CanceledException e) {
  2420. Log.e(TAG, "CanceledException unexpected here", e);
  2421. return false;
  2422. }
  2423. }
  2424. return false;
  2425. }
  2426. /** Returns true if the tech list filter matches the techs on the tag */
  2427. private boolean filterMatch(String[] tagTechs, String[] filterTechs) {
  2428. if (filterTechs == null || filterTechs.length == 0) return false;
  2429. for (String tech : filterTechs) {
  2430. if (Arrays.binarySearch(tagTechs, tech) < 0) {
  2431. return false;
  2432. }
  2433. }
  2434. return true;
  2435. }
  2436. // Dispatch to either an override pending intent or a standard startActivity()
  2437. private boolean dispatchTagInternal(Tag tag, NdefMessage[] msgs,
  2438. PendingIntent overrideIntent, IntentFilter[] overrideFilters,
  2439. String[][] overrideTechLists)
  2440. throws CanceledException{
  2441. Intent intent;
  2442. //
  2443. // Try the NDEF content specific dispatch
  2444. //
  2445. if (msgs != null && msgs.length > 0) {
  2446. NdefMessage msg = msgs[0];
  2447. NdefRecord[] records = msg.getRecords();
  2448. if (records.length > 0) {
  2449. // Found valid NDEF data, try to dispatch that first
  2450. NdefRecord record = records[0];
  2451. intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED);
  2452. if (setTypeOrDataFromNdef(intent, record)) {
  2453. // The record contains filterable data, try to start a matching activity
  2454. if (startDispatchActivity(intent, overrideIntent, overrideFilters,
  2455. overrideTechLists)) {
  2456. // If an activity is found then skip further dispatching
  2457. return true;
  2458. } else {
  2459. if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent);
  2460. }
  2461. }
  2462. }
  2463. }
  2464. //
  2465. // Try the technology specific dispatch
  2466. //
  2467. String[] tagTechs = tag.getTechList();
  2468. Arrays.sort(tagTechs);
  2469. if (overrideIntent != null) {
  2470. // There are dispatch overrides in place
  2471. if (overrideTechLists != null) {
  2472. for (String[] filterTechs : overrideTechLists) {
  2473. if (filterMatch(tagTechs, filterTechs)) {
  2474. // An override matched, send it to the foreground activity.
  2475. intent = buildTagIntent(tag, msgs,
  2476. NfcAdapter.ACTION_TECH_DISCOVERED);
  2477. overrideIntent.send(mContext, Activity.RESULT_OK, intent);
  2478. return true;
  2479. }
  2480. }
  2481. }
  2482. } else {
  2483. // Standard tech dispatch path
  2484. ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
  2485. ArrayList<ComponentInfo> registered = mTechListFilters.getComponents();
  2486. // Check each registered activity to see if it matches
  2487. for (ComponentInfo info : registered) {
  2488. // Don't allow wild card matching
  2489. if (filterMatch(tagTechs, info.techs)) {
  2490. // Add the activity as a match if it's not already in the list
  2491. if (!matches.contains(info.resolveInfo)) {
  2492. matches.add(info.resolveInfo);
  2493. }
  2494. }
  2495. }
  2496. if (matches.size() == 1) {
  2497. // Single match, launch directly
  2498. intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED);
  2499. ResolveInfo info = matches.get(0);
  2500. intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
  2501. try {
  2502. mContext.startActivity(intent);
  2503. return true;
  2504. } catch (ActivityNotFoundException e) {
  2505. if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
  2506. }
  2507. } else if (matches.size() > 1) {
  2508. // Multiple matches, show a custom activity chooser dialog
  2509. intent = new Intent(mContext, TechListChooserActivity.class);
  2510. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  2511. intent.putExtra(Intent.EXTRA_INTENT,
  2512. buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECH_DISCOVERED));
  2513. intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
  2514. matches);
  2515. try {
  2516. mContext.startActivity(intent);
  2517. return true;
  2518. } catch (ActivityNotFoundException e) {
  2519. if (DBG) Log.w(TAG, "No activities for technology handling of " + intent);
  2520. }
  2521. } else {
  2522. // No matches, move on
  2523. if (DBG) Log.w(TAG, "No activities for technology handling");
  2524. }
  2525. }
  2526. //
  2527. // Try the generic intent
  2528. //
  2529. intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED);
  2530. if (startDispatchActivity(intent, overrideIntent, overrideFilters, overrideTechLists)) {
  2531. return true;
  2532. } else {
  2533. Log.e(TAG, "No tag fallback activity found for " + intent);
  2534. return false;
  2535. }
  2536. }
  2537. private boolean startDispatchActivity(Intent intent, PendingIntent overrideIntent,
  2538. IntentFilter[] overrideFilters, String[][] overrideTechLists)
  2539. throws CanceledException {
  2540. if (overrideIntent != null) {
  2541. boolean found = false;
  2542. if (overrideFilters == null && overrideTechLists == null) {
  2543. // No filters means to always dispatch regardless of match
  2544. found = true;
  2545. } else if (overrideFilters != null) {
  2546. for (IntentFilter filter : overrideFilters) {
  2547. if (filter.match(mContext.getContentResolver(), intent, false, TAG) >= 0) {
  2548. found = true;
  2549. break;
  2550. }
  2551. }
  2552. }
  2553. if (found) {
  2554. Log.i(TAG, "Dispatching to override intent " + overrideIntent);
  2555. overrideIntent.send(mContext, Activity.RESULT_OK, intent);
  2556. return true;
  2557. } else {
  2558. return false;
  2559. }
  2560. } else {
  2561. try {
  2562. // If the current app called stopAppSwitches() then our startActivity()
  2563. // can be delayed for several seconds. This happens with the default home
  2564. // screen. As a system service we can override this behavior with
  2565. // resumeAppSwitches()
  2566. mIActivityManager.resumeAppSwitches();
  2567. } catch (RemoteException e) { }
  2568. try {
  2569. mContext.startActivity(intent);
  2570. return true;
  2571. } catch (ActivityNotFoundException e) {
  2572. return false;
  2573. }
  2574. }
  2575. }
  2576. }
  2577. private NfcServiceHandler mHandler = new NfcServiceHandler();
  2578. private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> {
  2579. @Override
  2580. protected Void doInBackground(Boolean... enable) {
  2581. if (enable != null && enable.length > 0 && enable[0]) {
  2582. synchronized (NfcService.this) {
  2583. mScreenOn = true;
  2584. applyRouting();
  2585. }
  2586. } else {
  2587. synchronized (NfcService.this) {
  2588. mWakeLock.acquire();
  2589. mScreenOn = false;
  2590. applyRouting();
  2591. maybeDisconnectTarget();
  2592. mWakeLock.release();
  2593. }
  2594. }
  2595. return null;
  2596. }
  2597. }
  2598. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  2599. @Override
  2600. public void onReceive(Context context, Intent intent) {
  2601. if (intent.getAction().equals(
  2602. NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
  2603. if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION");
  2604. /* Restart polling loop for notification */
  2605. applyRouting();
  2606. } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
  2607. // Perform discovery enable in thread to protect against ANR when the
  2608. // NFC stack wedges. This is *not* the correct way to fix this issue -
  2609. // configuration of the local NFC adapter should be very quick and should
  2610. // be safe on the main thread, and the NFC stack should not wedge.
  2611. new EnableDisableDiscoveryTask().execute(new Boolean(true));
  2612. } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
  2613. // Perform discovery disable in thread to protect against ANR when the
  2614. // NFC stack wedges. This is *not* the correct way to fix this issue -
  2615. // configuration of the local NFC adapter should be very quick and should
  2616. // be safe on the main thread, and the NFC stack should not wedge.
  2617. new EnableDisableDiscoveryTask().execute(new Boolean(false));
  2618. } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
  2619. executeSeReset();
  2620. } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
  2621. boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
  2622. if (dataRemoved) {
  2623. Uri data = intent.getData();
  2624. if (data == null) return;
  2625. String packageName = data.getSchemeSpecificPart();
  2626. synchronized (NfcService.this) {
  2627. if (mSePackages.contains(packageName)) {
  2628. executeSeReset();
  2629. mSePackages.remove(packageName);
  2630. }
  2631. }
  2632. }
  2633. }
  2634. }
  2635. };
  2636. }