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