NfcService.java revision 93915e1c6fe6d5d16fcebeda610782bf5812c9b4
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 17package com.android.nfc; 18 19import com.android.internal.nfc.LlcpServiceSocket; 20import com.android.internal.nfc.LlcpSocket; 21import com.android.nfc.mytag.MyTagClient; 22import com.android.nfc.mytag.MyTagServer; 23 24import android.app.Application; 25import android.app.StatusBarManager; 26import android.content.ActivityNotFoundException; 27import android.content.BroadcastReceiver; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.content.SharedPreferences; 32import android.nfc.ErrorCodes; 33import android.nfc.FormatException; 34import android.nfc.ILlcpConnectionlessSocket; 35import android.nfc.ILlcpServiceSocket; 36import android.nfc.ILlcpSocket; 37import android.nfc.INfcAdapter; 38import android.nfc.INfcTag; 39import android.nfc.IP2pInitiator; 40import android.nfc.IP2pTarget; 41import android.nfc.LlcpPacket; 42import android.nfc.NdefMessage; 43import android.nfc.NdefTag; 44import android.nfc.NfcAdapter; 45import android.nfc.Tag; 46import android.os.AsyncTask; 47import android.os.Handler; 48import android.os.Message; 49import android.os.RemoteException; 50import android.os.ServiceManager; 51import android.util.Log; 52 53import java.io.ByteArrayOutputStream; 54import java.io.FileInputStream; 55import java.io.FileNotFoundException; 56import java.io.FileOutputStream; 57import java.io.IOException; 58import java.util.HashMap; 59import java.util.LinkedList; 60import java.util.ListIterator; 61 62public class NfcService extends Application { 63 private static final String MY_TAG_FILE_NAME = "mytag"; 64 65 static { 66 System.loadLibrary("nfc_jni"); 67 } 68 69 public static final String SERVICE_NAME = "nfc"; 70 71 private static final String TAG = "NfcService"; 72 73 private static final String NFC_PERM = android.Manifest.permission.NFC; 74 private static final String NFC_PERM_ERROR = "NFC permission required"; 75 private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 76 private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 77 78 private static final String PREF = "NfcServicePrefs"; 79 80 private static final String PREF_NFC_ON = "nfc_on"; 81 private static final boolean NFC_ON_DEFAULT = true; 82 83 private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on"; 84 private static final boolean SECURE_ELEMENT_ON_DEFAULT = false; 85 86 private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id"; 87 private static final int SECURE_ELEMENT_ID_DEFAULT = 0; 88 89 private static final String PREF_LLCP_LTO = "llcp_lto"; 90 private static final int LLCP_LTO_DEFAULT = 250; 91 private static final int LLCP_LTO_MAX = 255; 92 93 /** Maximum Information Unit */ 94 private static final String PREF_LLCP_MIU = "llcp_miu"; 95 private static final int LLCP_MIU_DEFAULT = 128; 96 private static final int LLCP_MIU_MAX = 2176; 97 98 /** Well Known Service List */ 99 private static final String PREF_LLCP_WKS = "llcp_wks"; 100 private static final int LLCP_WKS_DEFAULT = 1; 101 private static final int LLCP_WKS_MAX = 15; 102 103 private static final String PREF_LLCP_OPT = "llcp_opt"; 104 private static final int LLCP_OPT_DEFAULT = 0; 105 private static final int LLCP_OPT_MAX = 3; 106 107 private static final String PREF_DISCOVERY_A = "discovery_a"; 108 private static final boolean DISCOVERY_A_DEFAULT = true; 109 110 private static final String PREF_DISCOVERY_B = "discovery_b"; 111 private static final boolean DISCOVERY_B_DEFAULT = true; 112 113 private static final String PREF_DISCOVERY_F = "discovery_f"; 114 private static final boolean DISCOVERY_F_DEFAULT = true; 115 116 private static final String PREF_DISCOVERY_15693 = "discovery_15693"; 117 private static final boolean DISCOVERY_15693_DEFAULT = true; 118 119 private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip"; 120 private static final boolean DISCOVERY_NFCIP_DEFAULT = true; 121 122 /** NFC Reader Discovery mode for enableDiscovery() */ 123 private static final int DISCOVERY_MODE_READER = 0; 124 125 /** Card Emulation Discovery mode for enableDiscovery() */ 126 private static final int DISCOVERY_MODE_CARD_EMULATION = 2; 127 128 private static final int LLCP_SERVICE_SOCKET_TYPE = 0; 129 private static final int LLCP_SOCKET_TYPE = 1; 130 private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2; 131 private static final int LLCP_SOCKET_NB_MAX = 5; // Maximum number of socket managed 132 private static final int LLCP_RW_MAX_VALUE = 15; // Receive Window 133 134 private static final int PROPERTY_LLCP_LTO = 0; 135 private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto"; 136 private static final int PROPERTY_LLCP_MIU = 1; 137 private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu"; 138 private static final int PROPERTY_LLCP_WKS = 2; 139 private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks"; 140 private static final int PROPERTY_LLCP_OPT = 3; 141 private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt"; 142 private static final int PROPERTY_NFC_DISCOVERY_A = 4; 143 private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A"; 144 private static final int PROPERTY_NFC_DISCOVERY_B = 5; 145 private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B"; 146 private static final int PROPERTY_NFC_DISCOVERY_F = 6; 147 private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica"; 148 private static final int PROPERTY_NFC_DISCOVERY_15693 = 7; 149 private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693"; 150 private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8; 151 private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip"; 152 153 static final int MSG_NDEF_TAG = 0; 154 static final int MSG_CARD_EMULATION = 1; 155 static final int MSG_LLCP_LINK_ACTIVATION = 2; 156 static final int MSG_LLCP_LINK_DEACTIVATED = 3; 157 static final int MSG_TARGET_DESELECTED = 4; 158 static final int MSG_SHOW_MY_TAG_ICON = 5; 159 static final int MSG_HIDE_MY_TAG_ICON = 6; 160 static final int MSG_MOCK_NDEF_TAG = 7; 161 162 // TODO: none of these appear to be synchronized but are 163 // read/written from different threads (notably Binder threads)... 164 private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>(); 165 private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 166 private int mGeneratedSocketHandle = 0; 167 private int mNbSocketCreated = 0; 168 private volatile boolean mIsNfcEnabled = false; 169 private int mSelectedSeId = 0; 170 private boolean mNfcSecureElementState; 171 172 // fields below are used in multiple threads and protected by synchronized(this) 173 private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 174 private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>(); 175 private boolean mScreenOn; 176 177 // fields below are final after onCreate() 178 private Context mContext; 179 private NativeNfcManager mManager; 180 private SharedPreferences mPrefs; 181 private SharedPreferences.Editor mPrefsEditor; 182 private MyTagServer mMyTagServer; 183 private MyTagClient mMyTagClient; 184 185 private static NfcService sService; 186 187 public static NfcService getInstance() { 188 return sService; 189 } 190 191 @Override 192 public void onCreate() { 193 super.onCreate(); 194 195 Log.i(TAG, "Starting NFC service"); 196 197 sService = this; 198 199 mContext = this; 200 mManager = new NativeNfcManager(mContext, this); 201 mManager.initializeNativeStructure(); 202 203 mMyTagServer = new MyTagServer(); 204 mMyTagClient = new MyTagClient(this); 205 206 mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 207 mPrefsEditor = mPrefs.edit(); 208 209 mIsNfcEnabled = false; // real preference read later 210 mScreenOn = true; // assume screen is on during boot 211 212 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 213 214 IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 215 filter.addAction(Intent.ACTION_SCREEN_OFF); 216 filter.addAction(Intent.ACTION_SCREEN_ON); 217 mContext.registerReceiver(mReceiver, filter); 218 219 Thread t = new Thread() { 220 @Override 221 public void run() { 222 boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT); 223 if (nfc_on) { 224 _enable(false); 225 } 226 } 227 }; 228 t.start(); 229 230 Context context = getApplicationContext(); 231 232 // Set this to null by default. If there isn't a tag on disk or if there 233 // was an error reading the tag then this will cause the status bar icon 234 // to be removed. 235 NdefMessage myTag = null; 236 237 FileInputStream input = null; 238 239 try { 240 input = context.openFileInput(MY_TAG_FILE_NAME); 241 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 242 243 byte[] buffer = new byte[4096]; 244 int read = 0; 245 while ((read = input.read(buffer)) > 0) { 246 bytes.write(buffer, 0, read); 247 } 248 249 myTag = new NdefMessage(bytes.toByteArray()); 250 } catch (FileNotFoundException e) { 251 // Ignore. 252 } catch (IOException e) { 253 Log.e(TAG, "Could not read mytag file: ", e); 254 context.deleteFile(MY_TAG_FILE_NAME); 255 } catch (FormatException e) { 256 Log.e(TAG, "Invalid NdefMessage for mytag", e); 257 context.deleteFile(MY_TAG_FILE_NAME); 258 } finally { 259 try { 260 if (input != null) { 261 input.close(); 262 } 263 } catch (IOException e) { 264 // Ignore 265 } 266 } 267 268 try { 269 mNfcAdapter.localSet(myTag); 270 } catch (RemoteException e) { 271 // Ignore 272 } 273 } 274 275 @Override 276 public void onTerminate() { 277 super.onTerminate(); 278 // NFC application is persistent, it should not be destroyed by framework 279 Log.wtf(TAG, "NFC service is under attack!"); 280 } 281 282 private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() { 283 /** Protected by "this" */ 284 NdefMessage mLocalMessage = null; 285 286 @Override 287 public boolean enable() throws RemoteException { 288 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 289 290 boolean isSuccess = false; 291 boolean previouslyEnabled = isEnabled(); 292 if (!previouslyEnabled) { 293 reset(); 294 isSuccess = _enable(previouslyEnabled); 295 } 296 return isSuccess; 297 } 298 299 @Override 300 public boolean disable() throws RemoteException { 301 boolean isSuccess = false; 302 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 303 boolean previouslyEnabled = isEnabled(); 304 Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled); 305 306 if (previouslyEnabled) { 307 /* tear down the my tag server */ 308 mMyTagServer.stop(); 309 isSuccess = mManager.deinitialize(); 310 Log.d(TAG, "NFC success of deinitialize = " + isSuccess); 311 if (isSuccess) { 312 mIsNfcEnabled = false; 313 } 314 } 315 316 updateNfcOnSetting(previouslyEnabled); 317 318 return isSuccess; 319 } 320 321 @Override 322 public int createLlcpConnectionlessSocket(int sap) throws RemoteException { 323 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 324 325 // Check if NFC is enabled 326 if (!mIsNfcEnabled) { 327 return ErrorCodes.ERROR_NOT_INITIALIZED; 328 } 329 330 /* Check SAP is not already used */ 331 332 /* Check nb socket created */ 333 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 334 /* Store the socket handle */ 335 int sockeHandle = mGeneratedSocketHandle; 336 337 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 338 NativeLlcpConnectionlessSocket socket; 339 340 socket = mManager.doCreateLlcpConnectionlessSocket(sap); 341 if (socket != null) { 342 synchronized(NfcService.this) { 343 /* Update the number of socket created */ 344 mNbSocketCreated++; 345 346 /* Add the socket into the socket map */ 347 mSocketMap.put(sockeHandle, socket); 348 } 349 return sockeHandle; 350 } else { 351 /* 352 * socket creation error - update the socket handle 353 * generation 354 */ 355 mGeneratedSocketHandle -= 1; 356 357 /* Get Error Status */ 358 int errorStatus = mManager.doGetLastError(); 359 360 switch (errorStatus) { 361 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 362 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 363 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 364 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 365 default: 366 return ErrorCodes.ERROR_SOCKET_CREATION; 367 } 368 } 369 } else { 370 /* Check SAP is not already used */ 371 if (!CheckSocketSap(sap)) { 372 return ErrorCodes.ERROR_SAP_USED; 373 } 374 375 NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap); 376 377 synchronized(NfcService.this) { 378 /* Add the socket into the socket map */ 379 mSocketMap.put(sockeHandle, socket); 380 381 /* Update the number of socket created */ 382 mNbSocketCreated++; 383 } 384 /* Create new registered socket */ 385 RegisteredSocket registeredSocket = new RegisteredSocket( 386 LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap); 387 388 /* Put this socket into a list of registered socket */ 389 mRegisteredSocketList.add(registeredSocket); 390 } 391 392 /* update socket handle generation */ 393 mGeneratedSocketHandle++; 394 395 return sockeHandle; 396 397 } else { 398 /* No socket available */ 399 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 400 } 401 402 } 403 404 @Override 405 public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength) 406 throws RemoteException { 407 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 408 409 // Check if NFC is enabled 410 if (!mIsNfcEnabled) { 411 return ErrorCodes.ERROR_NOT_INITIALIZED; 412 } 413 414 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 415 int sockeHandle = mGeneratedSocketHandle; 416 417 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 418 NativeLlcpServiceSocket socket; 419 420 socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 421 if (socket != null) { 422 synchronized(NfcService.this) { 423 /* Update the number of socket created */ 424 mNbSocketCreated++; 425 /* Add the socket into the socket map */ 426 mSocketMap.put(sockeHandle, socket); 427 } 428 } else { 429 /* socket creation error - update the socket handle counter */ 430 mGeneratedSocketHandle -= 1; 431 432 /* Get Error Status */ 433 int errorStatus = mManager.doGetLastError(); 434 435 switch (errorStatus) { 436 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 437 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 438 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 439 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 440 default: 441 return ErrorCodes.ERROR_SOCKET_CREATION; 442 } 443 } 444 } else { 445 446 /* Check SAP is not already used */ 447 if (!CheckSocketSap(sap)) { 448 return ErrorCodes.ERROR_SAP_USED; 449 } 450 451 /* Service Name */ 452 if (!CheckSocketServiceName(sn)) { 453 return ErrorCodes.ERROR_SERVICE_NAME_USED; 454 } 455 456 /* Check socket options */ 457 if (!CheckSocketOptions(miu, rw, linearBufferLength)) { 458 return ErrorCodes.ERROR_SOCKET_OPTIONS; 459 } 460 461 NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sn); 462 synchronized(NfcService.this) { 463 /* Add the socket into the socket map */ 464 mSocketMap.put(sockeHandle, socket); 465 466 /* Update the number of socket created */ 467 mNbSocketCreated++; 468 } 469 /* Create new registered socket */ 470 RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE, 471 sockeHandle, sap, sn, miu, rw, linearBufferLength); 472 473 /* Put this socket into a list of registered socket */ 474 mRegisteredSocketList.add(registeredSocket); 475 } 476 477 /* update socket handle generation */ 478 mGeneratedSocketHandle += 1; 479 480 Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle); 481 return sockeHandle; 482 } else { 483 /* No socket available */ 484 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 485 } 486 } 487 488 @Override 489 public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 490 throws RemoteException { 491 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 492 493 // Check if NFC is enabled 494 if (!mIsNfcEnabled) { 495 return ErrorCodes.ERROR_NOT_INITIALIZED; 496 } 497 498 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 499 500 int sockeHandle = mGeneratedSocketHandle; 501 502 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 503 Log.d(TAG, "creating llcp socket while activated"); 504 NativeLlcpSocket socket; 505 506 socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 507 508 if (socket != null) { 509 synchronized(NfcService.this) { 510 /* Update the number of socket created */ 511 mNbSocketCreated++; 512 /* Add the socket into the socket map */ 513 mSocketMap.put(sockeHandle, socket); 514 } 515 } else { 516 /* 517 * socket creation error - update the socket handle 518 * generation 519 */ 520 mGeneratedSocketHandle -= 1; 521 522 /* Get Error Status */ 523 int errorStatus = mManager.doGetLastError(); 524 525 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus)); 526 527 switch (errorStatus) { 528 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 529 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 530 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 531 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 532 default: 533 return ErrorCodes.ERROR_SOCKET_CREATION; 534 } 535 } 536 } else { 537 Log.d(TAG, "registering llcp socket while not activated"); 538 539 /* Check SAP is not already used */ 540 if (!CheckSocketSap(sap)) { 541 return ErrorCodes.ERROR_SAP_USED; 542 } 543 544 /* Check Socket options */ 545 if (!CheckSocketOptions(miu, rw, linearBufferLength)) { 546 return ErrorCodes.ERROR_SOCKET_OPTIONS; 547 } 548 549 NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw); 550 synchronized(NfcService.this) { 551 /* Add the socket into the socket map */ 552 mSocketMap.put(sockeHandle, socket); 553 554 /* Update the number of socket created */ 555 mNbSocketCreated++; 556 } 557 /* Create new registered socket */ 558 RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE, 559 sockeHandle, sap, miu, rw, linearBufferLength); 560 561 /* Put this socket into a list of registered socket */ 562 mRegisteredSocketList.add(registeredSocket); 563 } 564 565 /* update socket handle generation */ 566 mGeneratedSocketHandle++; 567 568 return sockeHandle; 569 } else { 570 /* No socket available */ 571 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 572 } 573 } 574 575 @Override 576 public int deselectSecureElement() throws RemoteException { 577 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 578 579 // Check if NFC is enabled 580 if (!mIsNfcEnabled) { 581 return ErrorCodes.ERROR_NOT_INITIALIZED; 582 } 583 584 if (mSelectedSeId == 0) { 585 return ErrorCodes.ERROR_NO_SE_CONNECTED; 586 } 587 588 mManager.doDeselectSecureElement(mSelectedSeId); 589 mNfcSecureElementState = false; 590 mSelectedSeId = 0; 591 592 /* store preference */ 593 mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false); 594 mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0); 595 mPrefsEditor.apply(); 596 597 return ErrorCodes.SUCCESS; 598 } 599 600 @Override 601 public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException { 602 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 603 return mLlcpConnectionlessSocketService; 604 } 605 606 @Override 607 public ILlcpSocket getLlcpInterface() throws RemoteException { 608 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 609 return mLlcpSocket; 610 } 611 612 @Override 613 public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException { 614 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 615 return mLlcpServerSocketService; 616 } 617 618 @Override 619 public INfcTag getNfcTagInterface() throws RemoteException { 620 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 621 return mNfcTagService; 622 } 623 624 @Override 625 public IP2pInitiator getP2pInitiatorInterface() throws RemoteException { 626 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 627 return mP2pInitiatorService; 628 } 629 630 @Override 631 public IP2pTarget getP2pTargetInterface() throws RemoteException { 632 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 633 return mP2pTargetService; 634 } 635 636 @Override 637 public String getProperties(String param) throws RemoteException { 638 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 639 640 if (param == null) { 641 return null; 642 } 643 644 if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { 645 return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT)); 646 } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { 647 return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT)); 648 } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { 649 return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT)); 650 } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { 651 return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT)); 652 } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { 653 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT)); 654 } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { 655 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT)); 656 } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { 657 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT)); 658 } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { 659 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT)); 660 } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { 661 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT)); 662 } else { 663 return "Unknown property"; 664 } 665 } 666 667 @Override 668 public int[] getSecureElementList() throws RemoteException { 669 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 670 671 int[] list = null; 672 if (mIsNfcEnabled == true) { 673 list = mManager.doGetSecureElementList(); 674 } 675 return list; 676 } 677 678 @Override 679 public int getSelectedSecureElement() throws RemoteException { 680 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 681 682 return mSelectedSeId; 683 } 684 685 @Override 686 public boolean isEnabled() throws RemoteException { 687 return mIsNfcEnabled; 688 } 689 690 @Override 691 public void openTagConnection(Tag tag) throws RemoteException { 692 // TODO: Remove obsolete code 693 } 694 695 @Override 696 public int selectSecureElement(int seId) throws RemoteException { 697 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 698 699 // Check if NFC is enabled 700 if (!mIsNfcEnabled) { 701 return ErrorCodes.ERROR_NOT_INITIALIZED; 702 } 703 704 if (mSelectedSeId == seId) { 705 return ErrorCodes.ERROR_SE_ALREADY_SELECTED; 706 } 707 708 if (mSelectedSeId != 0) { 709 return ErrorCodes.ERROR_SE_CONNECTED; 710 } 711 712 mSelectedSeId = seId; 713 mManager.doSelectSecureElement(mSelectedSeId); 714 715 /* store */ 716 mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true); 717 mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId); 718 mPrefsEditor.apply(); 719 720 mNfcSecureElementState = true; 721 722 return ErrorCodes.SUCCESS; 723 724 } 725 726 @Override 727 public int setProperties(String param, String value) throws RemoteException { 728 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 729 730 if (isEnabled()) { 731 return ErrorCodes.ERROR_NFC_ON; 732 } 733 734 int val; 735 736 /* Check params validity */ 737 if (param == null || value == null) { 738 return ErrorCodes.ERROR_INVALID_PARAM; 739 } 740 741 if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { 742 val = Integer.parseInt(value); 743 744 /* Check params */ 745 if (val > LLCP_LTO_MAX) 746 return ErrorCodes.ERROR_INVALID_PARAM; 747 748 /* Store value */ 749 mPrefsEditor.putInt(PREF_LLCP_LTO, val); 750 mPrefsEditor.apply(); 751 752 /* Update JNI */ 753 mManager.doSetProperties(PROPERTY_LLCP_LTO, val); 754 755 } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { 756 val = Integer.parseInt(value); 757 758 /* Check params */ 759 if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX)) 760 return ErrorCodes.ERROR_INVALID_PARAM; 761 762 /* Store value */ 763 mPrefsEditor.putInt(PREF_LLCP_MIU, val); 764 mPrefsEditor.apply(); 765 766 /* Update JNI */ 767 mManager.doSetProperties(PROPERTY_LLCP_MIU, val); 768 769 } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { 770 val = Integer.parseInt(value); 771 772 /* Check params */ 773 if (val > LLCP_WKS_MAX) 774 return ErrorCodes.ERROR_INVALID_PARAM; 775 776 /* Store value */ 777 mPrefsEditor.putInt(PREF_LLCP_WKS, val); 778 mPrefsEditor.apply(); 779 780 /* Update JNI */ 781 mManager.doSetProperties(PROPERTY_LLCP_WKS, val); 782 783 } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { 784 val = Integer.parseInt(value); 785 786 /* Check params */ 787 if (val > LLCP_OPT_MAX) 788 return ErrorCodes.ERROR_INVALID_PARAM; 789 790 /* Store value */ 791 mPrefsEditor.putInt(PREF_LLCP_OPT, val); 792 mPrefsEditor.apply(); 793 794 /* Update JNI */ 795 mManager.doSetProperties(PROPERTY_LLCP_OPT, val); 796 797 } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { 798 boolean b = Boolean.parseBoolean(value); 799 800 /* Store value */ 801 mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b); 802 mPrefsEditor.apply(); 803 804 /* Update JNI */ 805 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0); 806 807 } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { 808 boolean b = Boolean.parseBoolean(value); 809 810 /* Store value */ 811 mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b); 812 mPrefsEditor.apply(); 813 814 /* Update JNI */ 815 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0); 816 817 } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { 818 boolean b = Boolean.parseBoolean(value); 819 820 /* Store value */ 821 mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b); 822 mPrefsEditor.apply(); 823 824 /* Update JNI */ 825 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0); 826 827 } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { 828 boolean b = Boolean.parseBoolean(value); 829 830 /* Store value */ 831 mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b); 832 mPrefsEditor.apply(); 833 834 /* Update JNI */ 835 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0); 836 837 } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { 838 boolean b = Boolean.parseBoolean(value); 839 840 /* Store value */ 841 mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b); 842 mPrefsEditor.apply(); 843 844 /* Update JNI */ 845 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0); 846 847 } else { 848 return ErrorCodes.ERROR_INVALID_PARAM; 849 } 850 851 return ErrorCodes.SUCCESS; 852 } 853 854 @Override 855 public NdefMessage localGet() throws RemoteException { 856 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 857 858 synchronized (this) { 859 return mLocalMessage; 860 } 861 } 862 863 @Override 864 public void localSet(NdefMessage message) throws RemoteException { 865 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 866 867 synchronized (this) { 868 mLocalMessage = message; 869 Context context = NfcService.this.getApplicationContext(); 870 871 // Send a message to the UI thread to show or hide the icon so the requests are 872 // serialized and the icon can't get out of sync with reality. 873 if (message != null) { 874 FileOutputStream out = null; 875 876 try { 877 out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE); 878 out.write(message.toByteArray()); 879 } catch (IOException e) { 880 Log.e(TAG, "Could not write mytag file", e); 881 } finally { 882 try { 883 if (out != null) { 884 out.flush(); 885 out.close(); 886 } 887 } catch (IOException e) { 888 // Ignore 889 } 890 } 891 892 sendMessage(MSG_SHOW_MY_TAG_ICON, null); 893 } else { 894 context.deleteFile(MY_TAG_FILE_NAME); 895 sendMessage(MSG_HIDE_MY_TAG_ICON, null); 896 } 897 } 898 } 899 }; 900 901 private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() { 902 903 private final int CONNECT_FLAG = 0x01; 904 private final int CLOSE_FLAG = 0x02; 905 private final int RECV_FLAG = 0x04; 906 private final int SEND_FLAG = 0x08; 907 908 private int concurrencyFlags; 909 private Object sync; 910 911 @Override 912 public int close(int nativeHandle) throws RemoteException { 913 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 914 915 NativeLlcpSocket socket = null; 916 boolean isSuccess = false; 917 918 // Check if NFC is enabled 919 if (!mIsNfcEnabled) { 920 return ErrorCodes.ERROR_NOT_INITIALIZED; 921 } 922 923 /* find the socket in the hmap */ 924 socket = (NativeLlcpSocket) findSocket(nativeHandle); 925 if (socket != null) { 926 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 927 isSuccess = socket.doClose(); 928 if (isSuccess) { 929 /* Remove the socket closed from the hmap */ 930 RemoveSocket(nativeHandle); 931 /* Update mNbSocketCreated */ 932 mNbSocketCreated--; 933 return ErrorCodes.SUCCESS; 934 } else { 935 return ErrorCodes.ERROR_IO; 936 } 937 } else { 938 /* Remove the socket closed from the hmap */ 939 RemoveSocket(nativeHandle); 940 941 /* Remove registered socket from the list */ 942 RemoveRegisteredSocket(nativeHandle); 943 944 /* Update mNbSocketCreated */ 945 mNbSocketCreated--; 946 947 return ErrorCodes.SUCCESS; 948 } 949 } else { 950 return ErrorCodes.ERROR_IO; 951 } 952 } 953 954 @Override 955 public int connect(int nativeHandle, int sap) throws RemoteException { 956 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 957 958 NativeLlcpSocket socket = null; 959 boolean isSuccess = false; 960 961 // Check if NFC is enabled 962 if (!mIsNfcEnabled) { 963 return ErrorCodes.ERROR_NOT_INITIALIZED; 964 } 965 966 /* find the socket in the hmap */ 967 socket = (NativeLlcpSocket) findSocket(nativeHandle); 968 if (socket != null) { 969 isSuccess = socket.doConnect(sap); 970 if (isSuccess) { 971 return ErrorCodes.SUCCESS; 972 } else { 973 return ErrorCodes.ERROR_IO; 974 } 975 } else { 976 return ErrorCodes.ERROR_IO; 977 } 978 979 } 980 981 @Override 982 public int connectByName(int nativeHandle, String sn) throws RemoteException { 983 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 984 985 NativeLlcpSocket socket = null; 986 boolean isSuccess = false; 987 988 // Check if NFC is enabled 989 if (!mIsNfcEnabled) { 990 return ErrorCodes.ERROR_NOT_INITIALIZED; 991 } 992 993 /* find the socket in the hmap */ 994 socket = (NativeLlcpSocket) findSocket(nativeHandle); 995 if (socket != null) { 996 isSuccess = socket.doConnectBy(sn); 997 if (isSuccess) { 998 return ErrorCodes.SUCCESS; 999 } else { 1000 return ErrorCodes.ERROR_IO; 1001 } 1002 } else { 1003 return ErrorCodes.ERROR_IO; 1004 } 1005 1006 } 1007 1008 @Override 1009 public int getLocalSap(int nativeHandle) throws RemoteException { 1010 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1011 1012 NativeLlcpSocket socket = null; 1013 1014 // Check if NFC is enabled 1015 if (!mIsNfcEnabled) { 1016 return ErrorCodes.ERROR_NOT_INITIALIZED; 1017 } 1018 1019 /* find the socket in the hmap */ 1020 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1021 if (socket != null) { 1022 return socket.getSap(); 1023 } else { 1024 return 0; 1025 } 1026 } 1027 1028 @Override 1029 public int getLocalSocketMiu(int nativeHandle) throws RemoteException { 1030 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1031 1032 NativeLlcpSocket socket = null; 1033 1034 // Check if NFC is enabled 1035 if (!mIsNfcEnabled) { 1036 return ErrorCodes.ERROR_NOT_INITIALIZED; 1037 } 1038 1039 /* find the socket in the hmap */ 1040 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1041 if (socket != null) { 1042 return socket.getMiu(); 1043 } else { 1044 return 0; 1045 } 1046 } 1047 1048 @Override 1049 public int getLocalSocketRw(int nativeHandle) throws RemoteException { 1050 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1051 1052 NativeLlcpSocket socket = null; 1053 1054 // Check if NFC is enabled 1055 if (!mIsNfcEnabled) { 1056 return ErrorCodes.ERROR_NOT_INITIALIZED; 1057 } 1058 1059 /* find the socket in the hmap */ 1060 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1061 if (socket != null) { 1062 return socket.getRw(); 1063 } else { 1064 return 0; 1065 } 1066 } 1067 1068 @Override 1069 public int getRemoteSocketMiu(int nativeHandle) throws RemoteException { 1070 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1071 1072 NativeLlcpSocket socket = null; 1073 1074 // Check if NFC is enabled 1075 if (!mIsNfcEnabled) { 1076 return ErrorCodes.ERROR_NOT_INITIALIZED; 1077 } 1078 1079 /* find the socket in the hmap */ 1080 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1081 if (socket != null) { 1082 if (socket.doGetRemoteSocketMiu() != 0) { 1083 return socket.doGetRemoteSocketMiu(); 1084 } else { 1085 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1086 } 1087 } else { 1088 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1089 } 1090 } 1091 1092 @Override 1093 public int getRemoteSocketRw(int nativeHandle) throws RemoteException { 1094 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1095 1096 NativeLlcpSocket socket = null; 1097 1098 // Check if NFC is enabled 1099 if (!mIsNfcEnabled) { 1100 return ErrorCodes.ERROR_NOT_INITIALIZED; 1101 } 1102 1103 /* find the socket in the hmap */ 1104 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1105 if (socket != null) { 1106 if (socket.doGetRemoteSocketRw() != 0) { 1107 return socket.doGetRemoteSocketRw(); 1108 } else { 1109 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1110 } 1111 } else { 1112 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1113 } 1114 } 1115 1116 @Override 1117 public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException { 1118 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1119 1120 NativeLlcpSocket socket = null; 1121 int receiveLength = 0; 1122 1123 // Check if NFC is enabled 1124 if (!mIsNfcEnabled) { 1125 return ErrorCodes.ERROR_NOT_INITIALIZED; 1126 } 1127 1128 /* find the socket in the hmap */ 1129 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1130 if (socket != null) { 1131 receiveLength = socket.doReceive(receiveBuffer); 1132 if (receiveLength != 0) { 1133 return receiveLength; 1134 } else { 1135 return ErrorCodes.ERROR_IO; 1136 } 1137 } else { 1138 return ErrorCodes.ERROR_IO; 1139 } 1140 } 1141 1142 @Override 1143 public int send(int nativeHandle, byte[] data) throws RemoteException { 1144 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1145 1146 NativeLlcpSocket socket = null; 1147 boolean isSuccess = false; 1148 1149 // Check if NFC is enabled 1150 if (!mIsNfcEnabled) { 1151 return ErrorCodes.ERROR_NOT_INITIALIZED; 1152 } 1153 1154 /* find the socket in the hmap */ 1155 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1156 if (socket != null) { 1157 isSuccess = socket.doSend(data); 1158 if (isSuccess) { 1159 return ErrorCodes.SUCCESS; 1160 } else { 1161 return ErrorCodes.ERROR_IO; 1162 } 1163 } else { 1164 return ErrorCodes.ERROR_IO; 1165 } 1166 } 1167 }; 1168 1169 private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() { 1170 1171 @Override 1172 public int accept(int nativeHandle) throws RemoteException { 1173 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1174 1175 NativeLlcpServiceSocket socket = null; 1176 NativeLlcpSocket clientSocket = null; 1177 1178 // Check if NFC is enabled 1179 if (!mIsNfcEnabled) { 1180 return ErrorCodes.ERROR_NOT_INITIALIZED; 1181 } 1182 1183 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 1184 /* find the socket in the hmap */ 1185 socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); 1186 if (socket != null) { 1187 clientSocket = socket.doAccept(socket.getMiu(), 1188 socket.getRw(), socket.getLinearBufferLength()); 1189 if (clientSocket != null) { 1190 /* Add the socket into the socket map */ 1191 synchronized(this) { 1192 mSocketMap.put(clientSocket.getHandle(), clientSocket); 1193 mNbSocketCreated++; 1194 } 1195 return clientSocket.getHandle(); 1196 } else { 1197 return ErrorCodes.ERROR_IO; 1198 } 1199 } else { 1200 return ErrorCodes.ERROR_IO; 1201 } 1202 } else { 1203 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 1204 } 1205 1206 } 1207 1208 @Override 1209 public void close(int nativeHandle) throws RemoteException { 1210 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1211 1212 NativeLlcpServiceSocket socket = null; 1213 boolean isSuccess = false; 1214 1215 // Check if NFC is enabled 1216 if (!mIsNfcEnabled) { 1217 return; 1218 } 1219 1220 /* find the socket in the hmap */ 1221 socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); 1222 if (socket != null) { 1223 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 1224 isSuccess = socket.doClose(); 1225 if (isSuccess) { 1226 /* Remove the socket closed from the hmap */ 1227 RemoveSocket(nativeHandle); 1228 /* Update mNbSocketCreated */ 1229 mNbSocketCreated--; 1230 } 1231 } else { 1232 /* Remove the socket closed from the hmap */ 1233 RemoveSocket(nativeHandle); 1234 1235 /* Remove registered socket from the list */ 1236 RemoveRegisteredSocket(nativeHandle); 1237 1238 /* Update mNbSocketCreated */ 1239 mNbSocketCreated--; 1240 } 1241 } 1242 } 1243 }; 1244 1245 private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() { 1246 1247 @Override 1248 public void close(int nativeHandle) throws RemoteException { 1249 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1250 1251 NativeLlcpConnectionlessSocket socket = null; 1252 boolean isSuccess = false; 1253 1254 // Check if NFC is enabled 1255 if (!mIsNfcEnabled) { 1256 return; 1257 } 1258 1259 /* find the socket in the hmap */ 1260 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1261 if (socket != null) { 1262 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 1263 isSuccess = socket.doClose(); 1264 if (isSuccess) { 1265 /* Remove the socket closed from the hmap */ 1266 RemoveSocket(nativeHandle); 1267 /* Update mNbSocketCreated */ 1268 mNbSocketCreated--; 1269 } 1270 } else { 1271 /* Remove the socket closed from the hmap */ 1272 RemoveSocket(nativeHandle); 1273 1274 /* Remove registered socket from the list */ 1275 RemoveRegisteredSocket(nativeHandle); 1276 1277 /* Update mNbSocketCreated */ 1278 mNbSocketCreated--; 1279 } 1280 } 1281 } 1282 1283 @Override 1284 public int getSap(int nativeHandle) throws RemoteException { 1285 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1286 1287 NativeLlcpConnectionlessSocket socket = null; 1288 1289 // Check if NFC is enabled 1290 if (!mIsNfcEnabled) { 1291 return ErrorCodes.ERROR_NOT_INITIALIZED; 1292 } 1293 1294 /* find the socket in the hmap */ 1295 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1296 if (socket != null) { 1297 return socket.getSap(); 1298 } else { 1299 return 0; 1300 } 1301 } 1302 1303 @Override 1304 public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException { 1305 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1306 1307 NativeLlcpConnectionlessSocket socket = null; 1308 LlcpPacket packet; 1309 1310 // Check if NFC is enabled 1311 if (!mIsNfcEnabled) { 1312 return null; 1313 } 1314 1315 /* find the socket in the hmap */ 1316 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1317 if (socket != null) { 1318 packet = socket.doReceiveFrom(socket.getLinkMiu()); 1319 if (packet != null) { 1320 return packet; 1321 } 1322 return null; 1323 } else { 1324 return null; 1325 } 1326 } 1327 1328 @Override 1329 public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException { 1330 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1331 1332 NativeLlcpConnectionlessSocket socket = null; 1333 boolean isSuccess = false; 1334 1335 // Check if NFC is enabled 1336 if (!mIsNfcEnabled) { 1337 return ErrorCodes.ERROR_NOT_INITIALIZED; 1338 } 1339 1340 /* find the socket in the hmap */ 1341 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1342 if (socket != null) { 1343 isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer()); 1344 if (isSuccess) { 1345 return ErrorCodes.SUCCESS; 1346 } else { 1347 return ErrorCodes.ERROR_IO; 1348 } 1349 } else { 1350 return ErrorCodes.ERROR_IO; 1351 } 1352 } 1353 }; 1354 1355 private final INfcTag mNfcTagService = new INfcTag.Stub() { 1356 1357 @Override 1358 public int close(int nativeHandle) throws RemoteException { 1359 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1360 1361 NativeNfcTag tag = null; 1362 1363 // Check if NFC is enabled 1364 if (!mIsNfcEnabled) { 1365 return ErrorCodes.ERROR_NOT_INITIALIZED; 1366 } 1367 1368 /* find the tag in the hmap */ 1369 tag = (NativeNfcTag) findObject(nativeHandle); 1370 if (tag != null) { 1371 /* Remove the device from the hmap */ 1372 unregisterObject(nativeHandle); 1373 tag.disconnect(); 1374 return ErrorCodes.SUCCESS; 1375 } 1376 /* Restart polling loop for notification */ 1377 maybeEnableDiscovery(); 1378 return ErrorCodes.ERROR_DISCONNECT; 1379 } 1380 1381 @Override 1382 public int connect(int nativeHandle) throws RemoteException { 1383 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1384 1385 NativeNfcTag tag = null; 1386 1387 // Check if NFC is enabled 1388 if (!mIsNfcEnabled) { 1389 return ErrorCodes.ERROR_NOT_INITIALIZED; 1390 } 1391 1392 /* find the tag in the hmap */ 1393 tag = (NativeNfcTag) findObject(nativeHandle); 1394 if (tag == null) { 1395 return ErrorCodes.ERROR_DISCONNECT; 1396 } 1397 // TODO: register the tag as being locked rather than really connect 1398 return ErrorCodes.SUCCESS; 1399 } 1400 1401 @Override 1402 public String getType(int nativeHandle) throws RemoteException { 1403 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1404 1405 NativeNfcTag tag = null; 1406 String type; 1407 1408 // Check if NFC is enabled 1409 if (!mIsNfcEnabled) { 1410 return null; 1411 } 1412 1413 /* find the tag in the hmap */ 1414 tag = (NativeNfcTag) findObject(nativeHandle); 1415 if (tag != null) { 1416 type = tag.getType(); 1417 return type; 1418 } 1419 return null; 1420 } 1421 1422 @Override 1423 public byte[] getUid(int nativeHandle) throws RemoteException { 1424 NativeNfcTag tag = null; 1425 byte[] uid; 1426 1427 // Check if NFC is enabled 1428 if (!mIsNfcEnabled) { 1429 return null; 1430 } 1431 1432 /* find the tag in the hmap */ 1433 tag = (NativeNfcTag) findObject(nativeHandle); 1434 if (tag != null) { 1435 uid = tag.getUid(); 1436 return uid; 1437 } 1438 return null; 1439 } 1440 1441 @Override 1442 public boolean isPresent(int nativeHandle) throws RemoteException { 1443 NativeNfcTag tag = null; 1444 1445 // Check if NFC is enabled 1446 if (!mIsNfcEnabled) { 1447 return false; 1448 } 1449 1450 /* find the tag in the hmap */ 1451 tag = (NativeNfcTag) findObject(nativeHandle); 1452 if (tag == null) { 1453 return false; 1454 } 1455 1456 return tag.presenceCheck(); 1457 } 1458 1459 @Override 1460 public boolean isNdef(int nativeHandle) throws RemoteException { 1461 NativeNfcTag tag = null; 1462 boolean isSuccess = false; 1463 1464 // Check if NFC is enabled 1465 if (!mIsNfcEnabled) { 1466 return isSuccess; 1467 } 1468 1469 /* find the tag in the hmap */ 1470 tag = (NativeNfcTag) findObject(nativeHandle); 1471 if (tag != null) { 1472 isSuccess = tag.checkNdef(); 1473 } 1474 return isSuccess; 1475 } 1476 1477 @Override 1478 public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException { 1479 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1480 1481 NativeNfcTag tag = null; 1482 byte[] response; 1483 1484 // Check if NFC is enabled 1485 if (!mIsNfcEnabled) { 1486 return null; 1487 } 1488 1489 /* find the tag in the hmap */ 1490 tag = (NativeNfcTag) findObject(nativeHandle); 1491 if (tag != null) { 1492 response = tag.transceive(data); 1493 return response; 1494 } 1495 return null; 1496 } 1497 1498 @Override 1499 public NdefMessage read(int nativeHandle) throws RemoteException { 1500 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1501 1502 NativeNfcTag tag; 1503 1504 // Check if NFC is enabled 1505 if (!mIsNfcEnabled) { 1506 return null; 1507 } 1508 1509 /* find the tag in the hmap */ 1510 tag = (NativeNfcTag) findObject(nativeHandle); 1511 if (tag != null) { 1512 byte[] buf = tag.read(); 1513 if (buf == null) 1514 return null; 1515 1516 /* Create an NdefMessage */ 1517 try { 1518 return new NdefMessage(buf); 1519 } catch (FormatException e) { 1520 return null; 1521 } 1522 } 1523 return null; 1524 } 1525 1526 @Override 1527 public int write(int nativeHandle, NdefMessage msg) throws RemoteException { 1528 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1529 1530 NativeNfcTag tag; 1531 1532 // Check if NFC is enabled 1533 if (!mIsNfcEnabled) { 1534 return ErrorCodes.ERROR_NOT_INITIALIZED; 1535 } 1536 1537 /* find the tag in the hmap */ 1538 tag = (NativeNfcTag) findObject(nativeHandle); 1539 if (tag == null) { 1540 return ErrorCodes.ERROR_IO; 1541 } 1542 1543 if (tag.write(msg.toByteArray())) { 1544 return ErrorCodes.SUCCESS; 1545 } 1546 else { 1547 return ErrorCodes.ERROR_IO; 1548 } 1549 1550 } 1551 1552 @Override 1553 public int getLastError(int nativeHandle) throws RemoteException { 1554 // TODO Auto-generated method stub 1555 return 0; 1556 } 1557 1558 @Override 1559 public int getModeHint(int nativeHandle) throws RemoteException { 1560 // TODO Auto-generated method stub 1561 return 0; 1562 } 1563 1564 @Override 1565 public int makeReadOnly(int nativeHandle) throws RemoteException { 1566 // TODO Auto-generated method stub 1567 return 0; 1568 } 1569 1570 1571 }; 1572 1573 private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() { 1574 1575 @Override 1576 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1577 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1578 1579 NativeP2pDevice device; 1580 1581 // Check if NFC is enabled 1582 if (!mIsNfcEnabled) { 1583 return null; 1584 } 1585 1586 /* find the device in the hmap */ 1587 device = (NativeP2pDevice) findObject(nativeHandle); 1588 if (device != null) { 1589 byte[] buff = device.getGeneralBytes(); 1590 if (buff == null) 1591 return null; 1592 return buff; 1593 } 1594 return null; 1595 } 1596 1597 @Override 1598 public int getMode(int nativeHandle) throws RemoteException { 1599 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1600 1601 NativeP2pDevice device; 1602 1603 // Check if NFC is enabled 1604 if (!mIsNfcEnabled) { 1605 return ErrorCodes.ERROR_NOT_INITIALIZED; 1606 } 1607 1608 /* find the device in the hmap */ 1609 device = (NativeP2pDevice) findObject(nativeHandle); 1610 if (device != null) { 1611 return device.getMode(); 1612 } 1613 return ErrorCodes.ERROR_INVALID_PARAM; 1614 } 1615 1616 @Override 1617 public byte[] receive(int nativeHandle) throws RemoteException { 1618 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1619 1620 NativeP2pDevice device; 1621 1622 // Check if NFC is enabled 1623 if (!mIsNfcEnabled) { 1624 return null; 1625 } 1626 1627 /* find the device in the hmap */ 1628 device = (NativeP2pDevice) findObject(nativeHandle); 1629 if (device != null) { 1630 byte[] buff = device.doReceive(); 1631 if (buff == null) 1632 return null; 1633 return buff; 1634 } 1635 /* Restart polling loop for notification */ 1636 maybeEnableDiscovery(); 1637 return null; 1638 } 1639 1640 @Override 1641 public boolean send(int nativeHandle, byte[] data) throws RemoteException { 1642 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1643 1644 NativeP2pDevice device; 1645 boolean isSuccess = false; 1646 1647 // Check if NFC is enabled 1648 if (!mIsNfcEnabled) { 1649 return isSuccess; 1650 } 1651 1652 /* find the device in the hmap */ 1653 device = (NativeP2pDevice) findObject(nativeHandle); 1654 if (device != null) { 1655 isSuccess = device.doSend(data); 1656 } 1657 return isSuccess; 1658 } 1659 }; 1660 1661 private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() { 1662 1663 @Override 1664 public int connect(int nativeHandle) throws RemoteException { 1665 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1666 1667 NativeP2pDevice device; 1668 1669 // Check if NFC is enabled 1670 if (!mIsNfcEnabled) { 1671 return ErrorCodes.ERROR_NOT_INITIALIZED; 1672 } 1673 1674 /* find the device in the hmap */ 1675 device = (NativeP2pDevice) findObject(nativeHandle); 1676 if (device != null) { 1677 if (device.doConnect()) { 1678 return ErrorCodes.SUCCESS; 1679 } 1680 } 1681 return ErrorCodes.ERROR_CONNECT; 1682 } 1683 1684 @Override 1685 public boolean disconnect(int nativeHandle) throws RemoteException { 1686 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1687 1688 NativeP2pDevice device; 1689 boolean isSuccess = false; 1690 1691 // Check if NFC is enabled 1692 if (!mIsNfcEnabled) { 1693 return isSuccess; 1694 } 1695 1696 /* find the device in the hmap */ 1697 device = (NativeP2pDevice) findObject(nativeHandle); 1698 if (device != null) { 1699 if (isSuccess = device.doDisconnect()) { 1700 /* remove the device from the hmap */ 1701 unregisterObject(nativeHandle); 1702 /* Restart polling loop for notification */ 1703 maybeEnableDiscovery(); 1704 } 1705 } 1706 return isSuccess; 1707 1708 } 1709 1710 @Override 1711 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1712 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1713 1714 NativeP2pDevice device; 1715 1716 // Check if NFC is enabled 1717 if (!mIsNfcEnabled) { 1718 return null; 1719 } 1720 1721 /* find the device in the hmap */ 1722 device = (NativeP2pDevice) findObject(nativeHandle); 1723 if (device != null) { 1724 byte[] buff = device.getGeneralBytes(); 1725 if (buff == null) 1726 return null; 1727 return buff; 1728 } 1729 return null; 1730 } 1731 1732 @Override 1733 public int getMode(int nativeHandle) throws RemoteException { 1734 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1735 1736 NativeP2pDevice device; 1737 1738 // Check if NFC is enabled 1739 if (!mIsNfcEnabled) { 1740 return ErrorCodes.ERROR_NOT_INITIALIZED; 1741 } 1742 1743 /* find the device in the hmap */ 1744 device = (NativeP2pDevice) findObject(nativeHandle); 1745 if (device != null) { 1746 return device.getMode(); 1747 } 1748 return ErrorCodes.ERROR_INVALID_PARAM; 1749 } 1750 1751 @Override 1752 public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException { 1753 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1754 1755 NativeP2pDevice device; 1756 1757 // Check if NFC is enabled 1758 if (!mIsNfcEnabled) { 1759 return null; 1760 } 1761 1762 /* find the device in the hmap */ 1763 device = (NativeP2pDevice) findObject(nativeHandle); 1764 if (device != null) { 1765 byte[] buff = device.doTransceive(data); 1766 if (buff == null) 1767 return null; 1768 return buff; 1769 } 1770 return null; 1771 } 1772 }; 1773 1774 private boolean _enable(boolean oldEnabledState) { 1775 boolean isSuccess = mManager.initialize(); 1776 if (isSuccess) { 1777 applyProperties(); 1778 1779 /* Check Secure Element setting */ 1780 mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON, 1781 SECURE_ELEMENT_ON_DEFAULT); 1782 1783 if (mNfcSecureElementState) { 1784 int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID, 1785 SECURE_ELEMENT_ID_DEFAULT); 1786 int[] Se_list = mManager.doGetSecureElementList(); 1787 if (Se_list != null) { 1788 for (int i = 0; i < Se_list.length; i++) { 1789 if (Se_list[i] == secureElementId) { 1790 mManager.doSelectSecureElement(Se_list[i]); 1791 mSelectedSeId = Se_list[i]; 1792 break; 1793 } 1794 } 1795 } 1796 } 1797 1798 mIsNfcEnabled = true; 1799 1800 /* Start polling loop */ 1801 maybeEnableDiscovery(); 1802 1803 /* bring up the my tag server */ 1804 //mMyTagServer.start(); 1805 1806 } else { 1807 mIsNfcEnabled = false; 1808 } 1809 1810 updateNfcOnSetting(oldEnabledState); 1811 1812 return isSuccess; 1813 } 1814 1815 /** Enable active tag discovery if screen is on and NFC is enabled */ 1816 private synchronized void maybeEnableDiscovery() { 1817 if (mScreenOn && mIsNfcEnabled) { 1818 mManager.enableDiscovery(DISCOVERY_MODE_READER); 1819 } 1820 } 1821 1822 /** Disable active tag discovery if necessary */ 1823 private synchronized void maybeDisableDiscovery() { 1824 if (mIsNfcEnabled) { 1825 mManager.disableDiscovery(); 1826 } 1827 } 1828 1829 private void applyProperties() { 1830 mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT)); 1831 mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT)); 1832 mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT)); 1833 mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT)); 1834 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, 1835 mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0); 1836 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, 1837 mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0); 1838 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, 1839 mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0); 1840 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, 1841 mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0); 1842 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, 1843 mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0); 1844 } 1845 1846 private void updateNfcOnSetting(boolean oldEnabledState) { 1847 int state; 1848 1849 mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled); 1850 mPrefsEditor.apply(); 1851 1852 synchronized(this) { 1853 if (oldEnabledState != mIsNfcEnabled) { 1854 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE); 1855 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1856 intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled); 1857 mContext.sendBroadcast(intent); 1858 } 1859 } 1860 } 1861 1862 // Reset all internals 1863 private synchronized void reset() { 1864 // TODO: none of these appear to be synchronized but are 1865 // read/written from different threads (notably Binder threads)... 1866 1867 // Clear tables 1868 mObjectMap.clear(); 1869 mSocketMap.clear(); 1870 mRegisteredSocketList.clear(); 1871 1872 // Reset variables 1873 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 1874 mNbSocketCreated = 0; 1875 mIsNfcEnabled = false; 1876 mSelectedSeId = 0; 1877 } 1878 1879 private synchronized Object findObject(int key) { 1880 Object device = null; 1881 1882 device = mObjectMap.get(key); 1883 if (device == null) { 1884 Log.w(TAG, "Handle not found !"); 1885 } 1886 1887 return device; 1888 } 1889 1890 synchronized void registerTagObject(NativeNfcTag nativeTag) { 1891 mObjectMap.put(nativeTag.getHandle(), nativeTag); 1892 } 1893 1894 synchronized void unregisterObject(int handle) { 1895 mObjectMap.remove(handle); 1896 } 1897 1898 private synchronized Object findSocket(int key) { 1899 Object socket = null; 1900 1901 socket = mSocketMap.get(key); 1902 1903 return socket; 1904 } 1905 1906 private void RemoveSocket(int key) { 1907 mSocketMap.remove(key); 1908 } 1909 1910 private boolean CheckSocketSap(int sap) { 1911 /* List of sockets registered */ 1912 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 1913 1914 while (it.hasNext()) { 1915 RegisteredSocket registeredSocket = it.next(); 1916 1917 if (sap == registeredSocket.mSap) { 1918 /* SAP already used */ 1919 return false; 1920 } 1921 } 1922 return true; 1923 } 1924 1925 private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) { 1926 1927 if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) { 1928 return false; 1929 } 1930 return true; 1931 } 1932 1933 private boolean CheckSocketServiceName(String sn) { 1934 1935 /* List of sockets registered */ 1936 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 1937 1938 while (it.hasNext()) { 1939 RegisteredSocket registeredSocket = it.next(); 1940 1941 if (sn.equals(registeredSocket.mServiceName)) { 1942 /* Service Name already used */ 1943 return false; 1944 } 1945 } 1946 return true; 1947 } 1948 1949 private void RemoveRegisteredSocket(int nativeHandle) { 1950 /* check if sockets are registered */ 1951 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 1952 1953 while (it.hasNext()) { 1954 RegisteredSocket registeredSocket = it.next(); 1955 if (registeredSocket.mHandle == nativeHandle) { 1956 /* remove the registered socket from the list */ 1957 it.remove(); 1958 Log.d(TAG, "socket removed"); 1959 } 1960 } 1961 } 1962 1963 /* 1964 * RegisteredSocket class to store the creation request of socket until the 1965 * LLCP link in not activated 1966 */ 1967 private class RegisteredSocket { 1968 private final int mType; 1969 1970 private final int mHandle; 1971 1972 private final int mSap; 1973 1974 private int mMiu; 1975 1976 private int mRw; 1977 1978 private String mServiceName; 1979 1980 private int mlinearBufferLength; 1981 1982 RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw, 1983 int linearBufferLength) { 1984 mType = type; 1985 mHandle = handle; 1986 mSap = sap; 1987 mServiceName = sn; 1988 mRw = rw; 1989 mMiu = miu; 1990 mlinearBufferLength = linearBufferLength; 1991 } 1992 1993 RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) { 1994 mType = type; 1995 mHandle = handle; 1996 mSap = sap; 1997 mRw = rw; 1998 mMiu = miu; 1999 mlinearBufferLength = linearBufferLength; 2000 } 2001 2002 RegisteredSocket(int type, int handle, int sap) { 2003 mType = type; 2004 mHandle = handle; 2005 mSap = sap; 2006 } 2007 } 2008 2009 /** For use by code in this process */ 2010 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) { 2011 try { 2012 int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength); 2013 if (ErrorCodes.isError(handle)) { 2014 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2015 return null; 2016 } 2017 return new LlcpSocket(mLlcpSocket, handle); 2018 } catch (RemoteException e) { 2019 // This will never happen since the code is calling into it's own process 2020 throw new IllegalStateException("unable to talk to myself", e); 2021 } 2022 } 2023 2024 /** For use by code in this process */ 2025 public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw, 2026 int linearBufferLength) { 2027 try { 2028 int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 2029 if (ErrorCodes.isError(handle)) { 2030 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2031 return null; 2032 } 2033 return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle); 2034 } catch (RemoteException e) { 2035 // This will never happen since the code is calling into it's own process 2036 throw new IllegalStateException("unable to talk to myself", e); 2037 } 2038 } 2039 2040 private void activateLlcpLink() { 2041 /* check if sockets are registered */ 2042 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 2043 2044 Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size()); 2045 2046 /* Mark the link state */ 2047 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED; 2048 2049 while (it.hasNext()) { 2050 RegisteredSocket registeredSocket = it.next(); 2051 2052 switch (registeredSocket.mType) { 2053 case LLCP_SERVICE_SOCKET_TYPE: 2054 Log.d(TAG, "Registered Llcp Service Socket"); 2055 Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName); 2056 NativeLlcpServiceSocket serviceSocket; 2057 2058 serviceSocket = mManager.doCreateLlcpServiceSocket( 2059 registeredSocket.mSap, registeredSocket.mServiceName, 2060 registeredSocket.mMiu, registeredSocket.mRw, 2061 registeredSocket.mlinearBufferLength); 2062 2063 if (serviceSocket != null) { 2064 Log.d(TAG, "service socket created"); 2065 /* Add the socket into the socket map */ 2066 synchronized(NfcService.this) { 2067 mSocketMap.put(registeredSocket.mHandle, serviceSocket); 2068 } 2069 } else { 2070 Log.d(TAG, "FAILED to create service socket"); 2071 /* socket creation error - update the socket 2072 * handle counter */ 2073 mGeneratedSocketHandle -= 1; 2074 } 2075 break; 2076 2077 case LLCP_SOCKET_TYPE: 2078 Log.d(TAG, "Registered Llcp Socket"); 2079 NativeLlcpSocket clientSocket; 2080 clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap, 2081 registeredSocket.mMiu, registeredSocket.mRw, 2082 registeredSocket.mlinearBufferLength); 2083 if (clientSocket != null) { 2084 Log.d(TAG, "socket created"); 2085 /* Add the socket into the socket map */ 2086 synchronized(NfcService.this) { 2087 mSocketMap.put(registeredSocket.mHandle, clientSocket); 2088 } 2089 } else { 2090 Log.d(TAG, "FAILED to create service socket"); 2091 /* socket creation error - update the socket 2092 * handle counter */ 2093 mGeneratedSocketHandle -= 1; 2094 } 2095 break; 2096 2097 case LLCP_CONNECTIONLESS_SOCKET_TYPE: 2098 Log.d(TAG, "Registered Llcp Connectionless Socket"); 2099 NativeLlcpConnectionlessSocket connectionlessSocket; 2100 connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket( 2101 registeredSocket.mSap); 2102 if (connectionlessSocket != null) { 2103 Log.d(TAG, "connectionless socket created"); 2104 /* Add the socket into the socket map */ 2105 synchronized(NfcService.this) { 2106 mSocketMap.put(registeredSocket.mHandle, connectionlessSocket); 2107 } 2108 } else { 2109 Log.d(TAG, "FAILED to create service socket"); 2110 /* socket creation error - update the socket 2111 * handle counter */ 2112 mGeneratedSocketHandle -= 1; 2113 } 2114 break; 2115 } 2116 } 2117 2118 /* Remove all registered socket from the list */ 2119 mRegisteredSocketList.clear(); 2120 2121 /* Broadcast Intent Link LLCP activated */ 2122 Intent LlcpLinkIntent = new Intent(); 2123 LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED); 2124 2125 LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED, 2126 NfcAdapter.LLCP_LINK_STATE_ACTIVATED); 2127 2128 Log.d(TAG, "Broadcasting LLCP activation"); 2129 mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM); 2130 } 2131 2132 public void sendMockNdefTag(NdefMessage msg) { 2133 NdefTag tag = NdefTag.createMockNdefTag(new byte[] { 0x00 }, 2134 new String[] { Tag.TARGET_OTHER }, 2135 null, null, new String[] { NdefTag.TARGET_OTHER }, 2136 new NdefMessage[][] { new NdefMessage[] { msg } }); 2137 sendMessage(MSG_MOCK_NDEF_TAG, tag); 2138 } 2139 2140 void sendMessage(int what, Object obj) { 2141 Message msg = mHandler.obtainMessage(); 2142 msg.what = what; 2143 msg.obj = obj; 2144 mHandler.sendMessage(msg); 2145 } 2146 2147 private final Handler mHandler = new Handler() { 2148 @Override 2149 public void handleMessage(Message msg) { 2150 switch (msg.what) { 2151 case MSG_MOCK_NDEF_TAG: { 2152 NdefTag tag = (NdefTag) msg.obj; 2153 Intent intent = buildNdefTagIntent(tag); 2154 Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 2155 Log.d(TAG, tag.toString()); 2156 try { 2157 mContext.startActivity(intent); 2158 } catch (ActivityNotFoundException e) { 2159 Log.w(TAG, "No activity found for mock tag"); 2160 } 2161 } 2162 2163 case MSG_NDEF_TAG: 2164 Log.d(TAG, "Tag detected, notifying applications"); 2165 NativeNfcTag nativeTag = (NativeNfcTag) msg.obj; 2166 if (nativeTag.connect()) { 2167 if (nativeTag.checkNdef()) { 2168 boolean generateEmptyIntent = false; 2169 byte[] buff = nativeTag.read(); 2170 if (buff != null) { 2171 NdefMessage[] msgNdef = new NdefMessage[1]; 2172 try { 2173 msgNdef[0] = new NdefMessage(buff); 2174 NdefTag tag = new NdefTag(nativeTag.getUid(), 2175 TagTarget.internalTypeToRawTargets(nativeTag.getType()), 2176 null, null, nativeTag.getHandle(), 2177 TagTarget.internalTypeToNdefTargets(nativeTag.getType()), 2178 new NdefMessage[][] {msgNdef}); 2179 Intent intent = buildNdefTagIntent(tag); 2180 Log.d(TAG, "NDEF tag found, starting corresponding activity"); 2181 Log.d(TAG, tag.toString()); 2182 try { 2183 mContext.startActivity(intent); 2184 registerTagObject(nativeTag); 2185 } catch (ActivityNotFoundException e) { 2186 Log.w(TAG, "No activity found, disconnecting"); 2187 nativeTag.disconnect(); 2188 } 2189 } catch (FormatException e) { 2190 // Create an intent anyway, without NDEF messages 2191 generateEmptyIntent = true; 2192 } 2193 } else { 2194 // Create an intent anyway, without NDEF messages 2195 generateEmptyIntent = true; 2196 } 2197 if (generateEmptyIntent) { 2198 // Create an intent with an empty ndef message array 2199 NdefTag tag = new NdefTag(nativeTag.getUid(), 2200 TagTarget.internalTypeToRawTargets(nativeTag.getType()), 2201 null, null, nativeTag.getHandle(), 2202 TagTarget.internalTypeToNdefTargets(nativeTag.getType()), 2203 new NdefMessage[][] { {} }); 2204 Intent intent = buildNdefTagIntent(tag); 2205 Log.d(TAG, "NDEF tag found, but length 0 or invalid format, starting corresponding activity"); 2206 try { 2207 mContext.startActivity(intent); 2208 registerTagObject(nativeTag); 2209 } catch (ActivityNotFoundException e) { 2210 Log.w(TAG, "No activity found, disconnecting"); 2211 nativeTag.disconnect(); 2212 } 2213 } 2214 } else { 2215 Intent intent = new Intent(); 2216 Tag tag = new Tag(nativeTag.getUid(), false, 2217 TagTarget.internalTypeToRawTargets(nativeTag.getType()), 2218 null, null, nativeTag.getHandle()); 2219 intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED); 2220 intent.putExtra(NfcAdapter.EXTRA_TAG, tag); 2221 intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId()); 2222 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2223 Log.d(TAG, "Non-NDEF tag found, starting corresponding activity"); 2224 Log.d(TAG, tag.toString()); 2225 try { 2226 mContext.startActivity(intent); 2227 registerTagObject(nativeTag); 2228 } catch (ActivityNotFoundException e) { 2229 Log.w(TAG, "No activity found, disconnecting"); 2230 nativeTag.disconnect(); 2231 } 2232 } 2233 } else { 2234 Log.w(TAG, "Failed to connect to tag"); 2235 nativeTag.disconnect(); 2236 } 2237 break; 2238 case MSG_CARD_EMULATION: 2239 Log.d(TAG, "Card Emulation message"); 2240 byte[] aid = (byte[]) msg.obj; 2241 /* Send broadcast ordered */ 2242 Intent TransactionIntent = new Intent(); 2243 TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED); 2244 TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid); 2245 Log.d(TAG, "Broadcasting Card Emulation event"); 2246 mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM); 2247 break; 2248 2249 case MSG_LLCP_LINK_ACTIVATION: 2250 NativeP2pDevice device = (NativeP2pDevice) msg.obj; 2251 2252 Log.d(TAG, "LLCP Activation message"); 2253 2254 if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) { 2255 Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 2256 if (device.doConnect()) { 2257 /* Check Llcp compliancy */ 2258 if (mManager.doCheckLlcp()) { 2259 /* Activate Llcp Link */ 2260 if (mManager.doActivateLlcp()) { 2261 Log.d(TAG, "Initiator Activate LLCP OK"); 2262 activateLlcpLink(); 2263 } else { 2264 /* should not happen */ 2265 Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect."); 2266 device.doDisconnect(); 2267 } 2268 2269 } else { 2270 Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 2271 device.doDisconnect(); 2272 } 2273 } else { 2274 Log.d(TAG, "Cannot connect remote Target. Restart polling loop."); 2275 /* resume should be done in doConnect */ 2276 } 2277 2278 } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) { 2279 Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 2280 /* Check Llcp compliancy */ 2281 if (mManager.doCheckLlcp()) { 2282 /* Activate Llcp Link */ 2283 if (mManager.doActivateLlcp()) { 2284 Log.d(TAG, "Target Activate LLCP OK"); 2285 activateLlcpLink(); 2286 } 2287 } else { 2288 Log.d(TAG, "checkLlcp failed"); 2289 } 2290 } 2291 break; 2292 2293 case MSG_LLCP_LINK_DEACTIVATED: 2294 device = (NativeP2pDevice) msg.obj; 2295 2296 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 2297 /* Restart polling loop */ 2298 device.doDisconnect(); 2299 2300 /* Mark the link state */ 2301 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 2302 2303 /* Broadcast Intent Link LLCP activated */ 2304 Intent LlcpLinkIntent = new Intent(); 2305 LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED); 2306 LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED, 2307 NfcAdapter.LLCP_LINK_STATE_DEACTIVATED); 2308 Log.d(TAG, "Broadcasting LLCP deactivation"); 2309 mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM); 2310 break; 2311 2312 case MSG_TARGET_DESELECTED: 2313 /* Broadcast Intent Target Deselected */ 2314 Log.d(TAG, "Target Deselected"); 2315 Intent TargetDeselectedIntent = new Intent(); 2316 TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION); 2317 Log.d(TAG, "Broadcasting Intent"); 2318 mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM); 2319 break; 2320 2321 case MSG_SHOW_MY_TAG_ICON: { 2322 StatusBarManager sb = (StatusBarManager) getSystemService( 2323 Context.STATUS_BAR_SERVICE); 2324 sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0); 2325 break; 2326 } 2327 2328 case MSG_HIDE_MY_TAG_ICON: { 2329 StatusBarManager sb = (StatusBarManager) getSystemService( 2330 Context.STATUS_BAR_SERVICE); 2331 sb.removeIcon("nfc"); 2332 break; 2333 } 2334 2335 default: 2336 Log.e(TAG, "Unknown message received"); 2337 break; 2338 } 2339 } 2340 2341 private Intent buildNdefTagIntent(NdefTag tag) { 2342 Intent intent = new Intent(); 2343 intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED); 2344 intent.putExtra(NfcAdapter.EXTRA_TAG, tag); 2345 intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId()); 2346 intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, tag.getNdefMessages()); 2347 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2348 return intent; 2349 } 2350 }; 2351 2352 private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 2353 @Override 2354 protected Void doInBackground(Boolean... enable) { 2355 if (enable != null && enable.length > 0 && enable[0]) { 2356 synchronized (NfcService.this) { 2357 mScreenOn = true; 2358 maybeEnableDiscovery(); 2359 } 2360 } else { 2361 synchronized (NfcService.this) { 2362 mScreenOn = false; 2363 maybeDisableDiscovery(); 2364 } 2365 } 2366 return null; 2367 } 2368 } 2369 2370 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2371 @Override 2372 public void onReceive(Context context, Intent intent) { 2373 if (intent.getAction().equals( 2374 NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2375 Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 2376 2377 /* Restart polling loop for notification */ 2378 maybeEnableDiscovery(); 2379 2380 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 2381 // Perform discovery enable in thread to protect against ANR when the 2382 // NFC stack wedges. This is *not* the correct way to fix this issue - 2383 // configuration of the local NFC adapter should be very quick and should 2384 // be safe on the main thread, and the NFC stack should not wedge. 2385 new EnableDisableDiscoveryTask().execute(new Boolean(true)); 2386 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 2387 // Perform discovery disable in thread to protect against ANR when the 2388 // NFC stack wedges. This is *not* the correct way to fix this issue - 2389 // configuration of the local NFC adapter should be very quick and should 2390 // be safe on the main thread, and the NFC stack should not wedge. 2391 new EnableDisableDiscoveryTask().execute(new Boolean(false)); 2392 } 2393 } 2394 }; 2395} 2396