NfcService.java revision 03ee488afaa982ce934c5de399db9f9fa88c7d1e
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.net.Uri; 33import android.nfc.ErrorCodes; 34import android.nfc.FormatException; 35import android.nfc.ILlcpConnectionlessSocket; 36import android.nfc.ILlcpServiceSocket; 37import android.nfc.ILlcpSocket; 38import android.nfc.INfcAdapter; 39import android.nfc.INfcSecureElement; 40import android.nfc.INfcTag; 41import android.nfc.IP2pInitiator; 42import android.nfc.IP2pTarget; 43import android.nfc.LlcpPacket; 44import android.nfc.NdefMessage; 45import android.nfc.NdefRecord; 46import android.nfc.NfcAdapter; 47import android.nfc.Tag; 48import android.os.AsyncTask; 49import android.os.Bundle; 50import android.os.Handler; 51import android.os.Message; 52import android.os.PowerManager; 53import android.os.RemoteException; 54import android.os.ServiceManager; 55import android.util.Log; 56 57import java.io.ByteArrayOutputStream; 58import java.io.FileInputStream; 59import java.io.FileNotFoundException; 60import java.io.FileOutputStream; 61import java.io.IOException; 62import java.nio.charset.Charsets; 63import java.util.Arrays; 64import java.util.HashMap; 65import java.util.LinkedList; 66import java.util.ListIterator; 67import java.util.Timer; 68import java.util.TimerTask; 69 70public class NfcService extends Application { 71 static final boolean DBG = false; 72 73 private static final String MY_TAG_FILE_NAME = "mytag"; 74 75 static { 76 System.loadLibrary("nfc_jni"); 77 } 78 79 /** 80 * NFC Forum "URI Record Type Definition" 81 * 82 * This is a mapping of "URI Identifier Codes" to URI string prefixes, 83 * per section 3.2.2 of the NFC Forum URI Record Type Definition document. 84 */ 85 private static final String[] URI_PREFIX_MAP = new String[] { 86 "", // 0x00 87 "http://www.", // 0x01 88 "https://www.", // 0x02 89 "http://", // 0x03 90 "https://", // 0x04 91 "tel:", // 0x05 92 "mailto:", // 0x06 93 "ftp://anonymous:anonymous@", // 0x07 94 "ftp://ftp.", // 0x08 95 "ftps://", // 0x09 96 "sftp://", // 0x0A 97 "smb://", // 0x0B 98 "nfs://", // 0x0C 99 "ftp://", // 0x0D 100 "dav://", // 0x0E 101 "news:", // 0x0F 102 "telnet://", // 0x10 103 "imap:", // 0x11 104 "rtsp://", // 0x12 105 "urn:", // 0x13 106 "pop:", // 0x14 107 "sip:", // 0x15 108 "sips:", // 0x16 109 "tftp:", // 0x17 110 "btspp://", // 0x18 111 "btl2cap://", // 0x19 112 "btgoep://", // 0x1A 113 "tcpobex://", // 0x1B 114 "irdaobex://", // 0x1C 115 "file://", // 0x1D 116 "urn:epc:id:", // 0x1E 117 "urn:epc:tag:", // 0x1F 118 "urn:epc:pat:", // 0x20 119 "urn:epc:raw:", // 0x21 120 "urn:epc:", // 0x22 121 }; 122 123 public static final String SERVICE_NAME = "nfc"; 124 125 private static final String TAG = "NfcService"; 126 127 private static final String NFC_PERM = android.Manifest.permission.NFC; 128 private static final String NFC_PERM_ERROR = "NFC permission required"; 129 private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 130 private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 131 132 private static final String PREF = "NfcServicePrefs"; 133 134 private static final String PREF_NFC_ON = "nfc_on"; 135 private static final boolean NFC_ON_DEFAULT = true; 136 137 private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on"; 138 private static final boolean SECURE_ELEMENT_ON_DEFAULT = false; 139 140 private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id"; 141 private static final int SECURE_ELEMENT_ID_DEFAULT = 0; 142 143 private static final String PREF_LLCP_LTO = "llcp_lto"; 144 private static final int LLCP_LTO_DEFAULT = 150; 145 private static final int LLCP_LTO_MAX = 255; 146 147 /** Maximum Information Unit */ 148 private static final String PREF_LLCP_MIU = "llcp_miu"; 149 private static final int LLCP_MIU_DEFAULT = 128; 150 private static final int LLCP_MIU_MAX = 2176; 151 152 /** Well Known Service List */ 153 private static final String PREF_LLCP_WKS = "llcp_wks"; 154 private static final int LLCP_WKS_DEFAULT = 1; 155 private static final int LLCP_WKS_MAX = 15; 156 157 private static final String PREF_LLCP_OPT = "llcp_opt"; 158 private static final int LLCP_OPT_DEFAULT = 0; 159 private static final int LLCP_OPT_MAX = 3; 160 161 private static final String PREF_DISCOVERY_A = "discovery_a"; 162 private static final boolean DISCOVERY_A_DEFAULT = true; 163 164 private static final String PREF_DISCOVERY_B = "discovery_b"; 165 private static final boolean DISCOVERY_B_DEFAULT = true; 166 167 private static final String PREF_DISCOVERY_F = "discovery_f"; 168 private static final boolean DISCOVERY_F_DEFAULT = true; 169 170 private static final String PREF_DISCOVERY_15693 = "discovery_15693"; 171 private static final boolean DISCOVERY_15693_DEFAULT = true; 172 173 private static final String PREF_DISCOVERY_NFCIP = "discovery_nfcip"; 174 private static final boolean DISCOVERY_NFCIP_DEFAULT = true; 175 176 /** NFC Reader Discovery mode for enableDiscovery() */ 177 private static final int DISCOVERY_MODE_READER = 0; 178 179 /** Card Emulation Discovery mode for enableDiscovery() */ 180 private static final int DISCOVERY_MODE_CARD_EMULATION = 2; 181 182 private static final int LLCP_SERVICE_SOCKET_TYPE = 0; 183 private static final int LLCP_SOCKET_TYPE = 1; 184 private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2; 185 private static final int LLCP_SOCKET_NB_MAX = 5; // Maximum number of socket managed 186 private static final int LLCP_RW_MAX_VALUE = 15; // Receive Window 187 188 private static final int PROPERTY_LLCP_LTO = 0; 189 private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto"; 190 private static final int PROPERTY_LLCP_MIU = 1; 191 private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu"; 192 private static final int PROPERTY_LLCP_WKS = 2; 193 private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks"; 194 private static final int PROPERTY_LLCP_OPT = 3; 195 private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt"; 196 private static final int PROPERTY_NFC_DISCOVERY_A = 4; 197 private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A"; 198 private static final int PROPERTY_NFC_DISCOVERY_B = 5; 199 private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B"; 200 private static final int PROPERTY_NFC_DISCOVERY_F = 6; 201 private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica"; 202 private static final int PROPERTY_NFC_DISCOVERY_15693 = 7; 203 private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693"; 204 private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8; 205 private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip"; 206 207 static final int MSG_NDEF_TAG = 0; 208 static final int MSG_CARD_EMULATION = 1; 209 static final int MSG_LLCP_LINK_ACTIVATION = 2; 210 static final int MSG_LLCP_LINK_DEACTIVATED = 3; 211 static final int MSG_TARGET_DESELECTED = 4; 212 static final int MSG_SHOW_MY_TAG_ICON = 5; 213 static final int MSG_HIDE_MY_TAG_ICON = 6; 214 static final int MSG_MOCK_NDEF = 7; 215 216 // TODO: none of these appear to be synchronized but are 217 // read/written from different threads (notably Binder threads)... 218 private final LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>(); 219 private int mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 220 private int mGeneratedSocketHandle = 0; 221 private int mNbSocketCreated = 0; 222 private volatile boolean mIsNfcEnabled = false; 223 private int mSelectedSeId = 0; 224 private boolean mNfcSecureElementState; 225 226 // Secure element 227 private Timer mTimerOpenSmx; 228 private boolean isClosed = false; 229 private boolean isOpened = false; 230 private boolean mOpenSmxPending = false; 231 private NativeNfcSecureElement mSecureElement; 232 private int mSecureElementHandle; 233 234 // fields below are used in multiple threads and protected by synchronized(this) 235 private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 236 private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>(); 237 private boolean mScreenOn; 238 239 // fields below are final after onCreate() 240 private Context mContext; 241 private NativeNfcManager mManager; 242 private SharedPreferences mPrefs; 243 private SharedPreferences.Editor mPrefsEditor; 244 private PowerManager.WakeLock mWakeLock; 245 private MyTagServer mMyTagServer; 246 private MyTagClient mMyTagClient; 247 248 private static NfcService sService; 249 250 public static NfcService getInstance() { 251 return sService; 252 } 253 254 @Override 255 public void onCreate() { 256 super.onCreate(); 257 258 Log.i(TAG, "Starting NFC service"); 259 260 sService = this; 261 262 mContext = this; 263 mManager = new NativeNfcManager(mContext, this); 264 mManager.initializeNativeStructure(); 265 266 mMyTagServer = new MyTagServer(); 267 mMyTagClient = new MyTagClient(this); 268 269 mSecureElement = new NativeNfcSecureElement(); 270 271 mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 272 mPrefsEditor = mPrefs.edit(); 273 274 mIsNfcEnabled = false; // real preference read later 275 276 PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); 277 mScreenOn = pm.isScreenOn(); 278 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 279 280 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 281 282 IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 283 filter.addAction(Intent.ACTION_SCREEN_OFF); 284 filter.addAction(Intent.ACTION_SCREEN_ON); 285 mContext.registerReceiver(mReceiver, filter); 286 287 Thread t = new Thread() { 288 @Override 289 public void run() { 290 boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT); 291 if (nfc_on) { 292 _enable(false); 293 } 294 } 295 }; 296 t.start(); 297 } 298 299 @Override 300 public void onTerminate() { 301 super.onTerminate(); 302 // NFC application is persistent, it should not be destroyed by framework 303 Log.wtf(TAG, "NFC service is under attack!"); 304 } 305 306 private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() { 307 /** Protected by "this" */ 308 NdefMessage mLocalMessage = null; 309 310 @Override 311 public boolean enable() throws RemoteException { 312 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 313 314 boolean isSuccess = false; 315 boolean previouslyEnabled = isEnabled(); 316 if (!previouslyEnabled) { 317 reset(); 318 isSuccess = _enable(previouslyEnabled); 319 } 320 return isSuccess; 321 } 322 323 @Override 324 public boolean disable() throws RemoteException { 325 boolean isSuccess = false; 326 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 327 boolean previouslyEnabled = isEnabled(); 328 if (DBG) Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled); 329 330 if (previouslyEnabled) { 331 /* tear down the my tag server */ 332 mMyTagServer.stop(); 333 isSuccess = mManager.deinitialize(); 334 if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess); 335 if (isSuccess) { 336 mIsNfcEnabled = false; 337 } 338 } 339 340 updateNfcOnSetting(previouslyEnabled); 341 342 return isSuccess; 343 } 344 345 @Override 346 public int createLlcpConnectionlessSocket(int sap) throws RemoteException { 347 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 348 349 // Check if NFC is enabled 350 if (!mIsNfcEnabled) { 351 return ErrorCodes.ERROR_NOT_INITIALIZED; 352 } 353 354 /* Check SAP is not already used */ 355 356 /* Check nb socket created */ 357 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 358 /* Store the socket handle */ 359 int sockeHandle = mGeneratedSocketHandle; 360 361 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 362 NativeLlcpConnectionlessSocket socket; 363 364 socket = mManager.doCreateLlcpConnectionlessSocket(sap); 365 if (socket != null) { 366 synchronized(NfcService.this) { 367 /* Update the number of socket created */ 368 mNbSocketCreated++; 369 370 /* Add the socket into the socket map */ 371 mSocketMap.put(sockeHandle, socket); 372 } 373 return sockeHandle; 374 } else { 375 /* 376 * socket creation error - update the socket handle 377 * generation 378 */ 379 mGeneratedSocketHandle -= 1; 380 381 /* Get Error Status */ 382 int errorStatus = mManager.doGetLastError(); 383 384 switch (errorStatus) { 385 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 386 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 387 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 388 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 389 default: 390 return ErrorCodes.ERROR_SOCKET_CREATION; 391 } 392 } 393 } else { 394 /* Check SAP is not already used */ 395 if (!CheckSocketSap(sap)) { 396 return ErrorCodes.ERROR_SAP_USED; 397 } 398 399 NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap); 400 401 synchronized(NfcService.this) { 402 /* Add the socket into the socket map */ 403 mSocketMap.put(sockeHandle, socket); 404 405 /* Update the number of socket created */ 406 mNbSocketCreated++; 407 } 408 /* Create new registered socket */ 409 RegisteredSocket registeredSocket = new RegisteredSocket( 410 LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap); 411 412 /* Put this socket into a list of registered socket */ 413 mRegisteredSocketList.add(registeredSocket); 414 } 415 416 /* update socket handle generation */ 417 mGeneratedSocketHandle++; 418 419 return sockeHandle; 420 421 } else { 422 /* No socket available */ 423 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 424 } 425 426 } 427 428 @Override 429 public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength) 430 throws RemoteException { 431 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 432 433 // Check if NFC is enabled 434 if (!mIsNfcEnabled) { 435 return ErrorCodes.ERROR_NOT_INITIALIZED; 436 } 437 438 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 439 int sockeHandle = mGeneratedSocketHandle; 440 441 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 442 NativeLlcpServiceSocket socket; 443 444 socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 445 if (socket != null) { 446 synchronized(NfcService.this) { 447 /* Update the number of socket created */ 448 mNbSocketCreated++; 449 /* Add the socket into the socket map */ 450 mSocketMap.put(sockeHandle, socket); 451 } 452 } else { 453 /* socket creation error - update the socket handle counter */ 454 mGeneratedSocketHandle -= 1; 455 456 /* Get Error Status */ 457 int errorStatus = mManager.doGetLastError(); 458 459 switch (errorStatus) { 460 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 461 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 462 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 463 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 464 default: 465 return ErrorCodes.ERROR_SOCKET_CREATION; 466 } 467 } 468 } else { 469 470 /* Check SAP is not already used */ 471 if (!CheckSocketSap(sap)) { 472 return ErrorCodes.ERROR_SAP_USED; 473 } 474 475 /* Service Name */ 476 if (!CheckSocketServiceName(sn)) { 477 return ErrorCodes.ERROR_SERVICE_NAME_USED; 478 } 479 480 /* Check socket options */ 481 if (!CheckSocketOptions(miu, rw, linearBufferLength)) { 482 return ErrorCodes.ERROR_SOCKET_OPTIONS; 483 } 484 485 NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sap, sn, miu, rw, 486 linearBufferLength); 487 synchronized(NfcService.this) { 488 /* Add the socket into the socket map */ 489 mSocketMap.put(sockeHandle, socket); 490 491 /* Update the number of socket created */ 492 mNbSocketCreated++; 493 } 494 /* Create new registered socket */ 495 RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE, 496 sockeHandle, sap, sn, miu, rw, linearBufferLength); 497 498 /* Put this socket into a list of registered socket */ 499 mRegisteredSocketList.add(registeredSocket); 500 } 501 502 /* update socket handle generation */ 503 mGeneratedSocketHandle += 1; 504 505 if (DBG) Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle); 506 return sockeHandle; 507 } else { 508 /* No socket available */ 509 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 510 } 511 } 512 513 @Override 514 public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 515 throws RemoteException { 516 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 517 518 // Check if NFC is enabled 519 if (!mIsNfcEnabled) { 520 return ErrorCodes.ERROR_NOT_INITIALIZED; 521 } 522 523 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 524 525 int sockeHandle = mGeneratedSocketHandle; 526 527 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 528 if (DBG) Log.d(TAG, "creating llcp socket while activated"); 529 NativeLlcpSocket socket; 530 531 socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 532 533 if (socket != null) { 534 synchronized(NfcService.this) { 535 /* Update the number of socket created */ 536 mNbSocketCreated++; 537 /* Add the socket into the socket map */ 538 mSocketMap.put(sockeHandle, socket); 539 } 540 } else { 541 /* 542 * socket creation error - update the socket handle 543 * generation 544 */ 545 mGeneratedSocketHandle -= 1; 546 547 /* Get Error Status */ 548 int errorStatus = mManager.doGetLastError(); 549 550 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus)); 551 552 switch (errorStatus) { 553 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 554 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 555 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 556 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 557 default: 558 return ErrorCodes.ERROR_SOCKET_CREATION; 559 } 560 } 561 } else { 562 if (DBG) Log.d(TAG, "registering llcp socket while not activated"); 563 564 /* Check SAP is not already used */ 565 if (!CheckSocketSap(sap)) { 566 return ErrorCodes.ERROR_SAP_USED; 567 } 568 569 /* Check Socket options */ 570 if (!CheckSocketOptions(miu, rw, linearBufferLength)) { 571 return ErrorCodes.ERROR_SOCKET_OPTIONS; 572 } 573 574 NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw); 575 synchronized(NfcService.this) { 576 /* Add the socket into the socket map */ 577 mSocketMap.put(sockeHandle, socket); 578 579 /* Update the number of socket created */ 580 mNbSocketCreated++; 581 } 582 /* Create new registered socket */ 583 RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE, 584 sockeHandle, sap, miu, rw, linearBufferLength); 585 586 /* Put this socket into a list of registered socket */ 587 mRegisteredSocketList.add(registeredSocket); 588 } 589 590 /* update socket handle generation */ 591 mGeneratedSocketHandle++; 592 593 return sockeHandle; 594 } else { 595 /* No socket available */ 596 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 597 } 598 } 599 600 @Override 601 public int deselectSecureElement() throws RemoteException { 602 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 603 604 // Check if NFC is enabled 605 if (!mIsNfcEnabled) { 606 return ErrorCodes.ERROR_NOT_INITIALIZED; 607 } 608 609 if (mSelectedSeId == 0) { 610 return ErrorCodes.ERROR_NO_SE_CONNECTED; 611 } 612 613 mManager.doDeselectSecureElement(mSelectedSeId); 614 mNfcSecureElementState = false; 615 mSelectedSeId = 0; 616 617 /* store preference */ 618 mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false); 619 mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0); 620 mPrefsEditor.apply(); 621 622 return ErrorCodes.SUCCESS; 623 } 624 625 @Override 626 public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException { 627 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 628 return mLlcpConnectionlessSocketService; 629 } 630 631 @Override 632 public ILlcpSocket getLlcpInterface() throws RemoteException { 633 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 634 return mLlcpSocket; 635 } 636 637 @Override 638 public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException { 639 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 640 return mLlcpServerSocketService; 641 } 642 643 @Override 644 public INfcTag getNfcTagInterface() throws RemoteException { 645 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 646 return mNfcTagService; 647 } 648 649 @Override 650 public IP2pInitiator getP2pInitiatorInterface() throws RemoteException { 651 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 652 return mP2pInitiatorService; 653 } 654 655 @Override 656 public IP2pTarget getP2pTargetInterface() throws RemoteException { 657 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 658 return mP2pTargetService; 659 } 660 661 public INfcSecureElement getNfcSecureElementInterface() { 662 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 663 return mSecureElementService; 664 } 665 666 @Override 667 public String getProperties(String param) throws RemoteException { 668 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 669 670 if (param == null) { 671 return null; 672 } 673 674 if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { 675 return Integer.toString(mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT)); 676 } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { 677 return Integer.toString(mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT)); 678 } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { 679 return Integer.toString(mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT)); 680 } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { 681 return Integer.toString(mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT)); 682 } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { 683 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT)); 684 } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { 685 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT)); 686 } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { 687 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT)); 688 } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { 689 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT)); 690 } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { 691 return Boolean.toString(mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT)); 692 } else { 693 return "Unknown property"; 694 } 695 } 696 697 @Override 698 public int[] getSecureElementList() throws RemoteException { 699 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 700 701 int[] list = null; 702 if (mIsNfcEnabled == true) { 703 list = mManager.doGetSecureElementList(); 704 } 705 return list; 706 } 707 708 @Override 709 public int getSelectedSecureElement() throws RemoteException { 710 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 711 712 return mSelectedSeId; 713 } 714 715 @Override 716 public boolean isEnabled() throws RemoteException { 717 return mIsNfcEnabled; 718 } 719 720 @Override 721 public void openTagConnection(Tag tag) throws RemoteException { 722 // TODO: Remove obsolete code 723 } 724 725 @Override 726 public int selectSecureElement(int seId) throws RemoteException { 727 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 728 729 // Check if NFC is enabled 730 if (!mIsNfcEnabled) { 731 return ErrorCodes.ERROR_NOT_INITIALIZED; 732 } 733 734 if (mSelectedSeId == seId) { 735 return ErrorCodes.ERROR_SE_ALREADY_SELECTED; 736 } 737 738 if (mSelectedSeId != 0) { 739 return ErrorCodes.ERROR_SE_CONNECTED; 740 } 741 742 mSelectedSeId = seId; 743 mManager.doSelectSecureElement(mSelectedSeId); 744 745 /* store */ 746 mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true); 747 mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId); 748 mPrefsEditor.apply(); 749 750 mNfcSecureElementState = true; 751 752 return ErrorCodes.SUCCESS; 753 754 } 755 756 @Override 757 public int setProperties(String param, String value) throws RemoteException { 758 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 759 760 if (isEnabled()) { 761 return ErrorCodes.ERROR_NFC_ON; 762 } 763 764 int val; 765 766 /* Check params validity */ 767 if (param == null || value == null) { 768 return ErrorCodes.ERROR_INVALID_PARAM; 769 } 770 771 if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { 772 val = Integer.parseInt(value); 773 774 /* Check params */ 775 if (val > LLCP_LTO_MAX) 776 return ErrorCodes.ERROR_INVALID_PARAM; 777 778 /* Store value */ 779 mPrefsEditor.putInt(PREF_LLCP_LTO, val); 780 mPrefsEditor.apply(); 781 782 /* Update JNI */ 783 mManager.doSetProperties(PROPERTY_LLCP_LTO, val); 784 785 } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { 786 val = Integer.parseInt(value); 787 788 /* Check params */ 789 if ((val < LLCP_MIU_DEFAULT) || (val > LLCP_MIU_MAX)) 790 return ErrorCodes.ERROR_INVALID_PARAM; 791 792 /* Store value */ 793 mPrefsEditor.putInt(PREF_LLCP_MIU, val); 794 mPrefsEditor.apply(); 795 796 /* Update JNI */ 797 mManager.doSetProperties(PROPERTY_LLCP_MIU, val); 798 799 } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { 800 val = Integer.parseInt(value); 801 802 /* Check params */ 803 if (val > LLCP_WKS_MAX) 804 return ErrorCodes.ERROR_INVALID_PARAM; 805 806 /* Store value */ 807 mPrefsEditor.putInt(PREF_LLCP_WKS, val); 808 mPrefsEditor.apply(); 809 810 /* Update JNI */ 811 mManager.doSetProperties(PROPERTY_LLCP_WKS, val); 812 813 } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { 814 val = Integer.parseInt(value); 815 816 /* Check params */ 817 if (val > LLCP_OPT_MAX) 818 return ErrorCodes.ERROR_INVALID_PARAM; 819 820 /* Store value */ 821 mPrefsEditor.putInt(PREF_LLCP_OPT, val); 822 mPrefsEditor.apply(); 823 824 /* Update JNI */ 825 mManager.doSetProperties(PROPERTY_LLCP_OPT, val); 826 827 } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { 828 boolean b = Boolean.parseBoolean(value); 829 830 /* Store value */ 831 mPrefsEditor.putBoolean(PREF_DISCOVERY_A, b); 832 mPrefsEditor.apply(); 833 834 /* Update JNI */ 835 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, b ? 1 : 0); 836 837 } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { 838 boolean b = Boolean.parseBoolean(value); 839 840 /* Store value */ 841 mPrefsEditor.putBoolean(PREF_DISCOVERY_B, b); 842 mPrefsEditor.apply(); 843 844 /* Update JNI */ 845 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, b ? 1 : 0); 846 847 } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { 848 boolean b = Boolean.parseBoolean(value); 849 850 /* Store value */ 851 mPrefsEditor.putBoolean(PREF_DISCOVERY_F, b); 852 mPrefsEditor.apply(); 853 854 /* Update JNI */ 855 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, b ? 1 : 0); 856 857 } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { 858 boolean b = Boolean.parseBoolean(value); 859 860 /* Store value */ 861 mPrefsEditor.putBoolean(PREF_DISCOVERY_15693, b); 862 mPrefsEditor.apply(); 863 864 /* Update JNI */ 865 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, b ? 1 : 0); 866 867 } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { 868 boolean b = Boolean.parseBoolean(value); 869 870 /* Store value */ 871 mPrefsEditor.putBoolean(PREF_DISCOVERY_NFCIP, b); 872 mPrefsEditor.apply(); 873 874 /* Update JNI */ 875 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, b ? 1 : 0); 876 877 } else { 878 return ErrorCodes.ERROR_INVALID_PARAM; 879 } 880 881 return ErrorCodes.SUCCESS; 882 } 883 884 @Override 885 public NdefMessage localGet() throws RemoteException { 886 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 887 888 synchronized (this) { 889 return mLocalMessage; 890 } 891 } 892 893 @Override 894 public void localSet(NdefMessage message) throws RemoteException { 895 mContext.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 896 897 synchronized (this) { 898 mLocalMessage = message; 899 Context context = NfcService.this.getApplicationContext(); 900 901 // Send a message to the UI thread to show or hide the icon so the requests are 902 // serialized and the icon can't get out of sync with reality. 903 if (message != null) { 904 FileOutputStream out = null; 905 906 try { 907 out = context.openFileOutput(MY_TAG_FILE_NAME, Context.MODE_PRIVATE); 908 byte[] bytes = message.toByteArray(); 909 if (bytes.length == 0) { 910 Log.w(TAG, "Setting a empty mytag"); 911 } 912 913 out.write(bytes); 914 } catch (IOException e) { 915 Log.e(TAG, "Could not write mytag file", e); 916 } finally { 917 try { 918 if (out != null) { 919 out.flush(); 920 out.close(); 921 } 922 } catch (IOException e) { 923 // Ignore 924 } 925 } 926 927 // Only show the icon if NFC is enabled. 928 if (mIsNfcEnabled) { 929 sendMessage(MSG_SHOW_MY_TAG_ICON, null); 930 } 931 } else { 932 context.deleteFile(MY_TAG_FILE_NAME); 933 sendMessage(MSG_HIDE_MY_TAG_ICON, null); 934 } 935 } 936 } 937 }; 938 939 private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() { 940 941 private final int CONNECT_FLAG = 0x01; 942 private final int CLOSE_FLAG = 0x02; 943 private final int RECV_FLAG = 0x04; 944 private final int SEND_FLAG = 0x08; 945 946 private int concurrencyFlags; 947 private Object sync; 948 949 @Override 950 public int close(int nativeHandle) throws RemoteException { 951 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 952 953 NativeLlcpSocket socket = null; 954 boolean isSuccess = false; 955 956 // Check if NFC is enabled 957 if (!mIsNfcEnabled) { 958 return ErrorCodes.ERROR_NOT_INITIALIZED; 959 } 960 961 /* find the socket in the hmap */ 962 socket = (NativeLlcpSocket) findSocket(nativeHandle); 963 if (socket != null) { 964 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 965 isSuccess = socket.doClose(); 966 if (isSuccess) { 967 /* Remove the socket closed from the hmap */ 968 RemoveSocket(nativeHandle); 969 /* Update mNbSocketCreated */ 970 mNbSocketCreated--; 971 return ErrorCodes.SUCCESS; 972 } else { 973 return ErrorCodes.ERROR_IO; 974 } 975 } else { 976 /* Remove the socket closed from the hmap */ 977 RemoveSocket(nativeHandle); 978 979 /* Remove registered socket from the list */ 980 RemoveRegisteredSocket(nativeHandle); 981 982 /* Update mNbSocketCreated */ 983 mNbSocketCreated--; 984 985 return ErrorCodes.SUCCESS; 986 } 987 } else { 988 return ErrorCodes.ERROR_IO; 989 } 990 } 991 992 @Override 993 public int connect(int nativeHandle, int sap) throws RemoteException { 994 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 995 996 NativeLlcpSocket socket = null; 997 boolean isSuccess = false; 998 999 // Check if NFC is enabled 1000 if (!mIsNfcEnabled) { 1001 return ErrorCodes.ERROR_NOT_INITIALIZED; 1002 } 1003 1004 /* find the socket in the hmap */ 1005 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1006 if (socket != null) { 1007 isSuccess = socket.doConnect(sap); 1008 if (isSuccess) { 1009 return ErrorCodes.SUCCESS; 1010 } else { 1011 return ErrorCodes.ERROR_IO; 1012 } 1013 } else { 1014 return ErrorCodes.ERROR_IO; 1015 } 1016 1017 } 1018 1019 @Override 1020 public int connectByName(int nativeHandle, String sn) throws RemoteException { 1021 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1022 1023 NativeLlcpSocket socket = null; 1024 boolean isSuccess = false; 1025 1026 // Check if NFC is enabled 1027 if (!mIsNfcEnabled) { 1028 return ErrorCodes.ERROR_NOT_INITIALIZED; 1029 } 1030 1031 /* find the socket in the hmap */ 1032 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1033 if (socket != null) { 1034 isSuccess = socket.doConnectBy(sn); 1035 if (isSuccess) { 1036 return ErrorCodes.SUCCESS; 1037 } else { 1038 return ErrorCodes.ERROR_IO; 1039 } 1040 } else { 1041 return ErrorCodes.ERROR_IO; 1042 } 1043 1044 } 1045 1046 @Override 1047 public int getLocalSap(int nativeHandle) throws RemoteException { 1048 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1049 1050 NativeLlcpSocket socket = null; 1051 1052 // Check if NFC is enabled 1053 if (!mIsNfcEnabled) { 1054 return ErrorCodes.ERROR_NOT_INITIALIZED; 1055 } 1056 1057 /* find the socket in the hmap */ 1058 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1059 if (socket != null) { 1060 return socket.getSap(); 1061 } else { 1062 return 0; 1063 } 1064 } 1065 1066 @Override 1067 public int getLocalSocketMiu(int nativeHandle) throws RemoteException { 1068 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1069 1070 NativeLlcpSocket socket = null; 1071 1072 // Check if NFC is enabled 1073 if (!mIsNfcEnabled) { 1074 return ErrorCodes.ERROR_NOT_INITIALIZED; 1075 } 1076 1077 /* find the socket in the hmap */ 1078 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1079 if (socket != null) { 1080 return socket.getMiu(); 1081 } else { 1082 return 0; 1083 } 1084 } 1085 1086 @Override 1087 public int getLocalSocketRw(int nativeHandle) throws RemoteException { 1088 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1089 1090 NativeLlcpSocket socket = null; 1091 1092 // Check if NFC is enabled 1093 if (!mIsNfcEnabled) { 1094 return ErrorCodes.ERROR_NOT_INITIALIZED; 1095 } 1096 1097 /* find the socket in the hmap */ 1098 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1099 if (socket != null) { 1100 return socket.getRw(); 1101 } else { 1102 return 0; 1103 } 1104 } 1105 1106 @Override 1107 public int getRemoteSocketMiu(int nativeHandle) throws RemoteException { 1108 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1109 1110 NativeLlcpSocket socket = null; 1111 1112 // Check if NFC is enabled 1113 if (!mIsNfcEnabled) { 1114 return ErrorCodes.ERROR_NOT_INITIALIZED; 1115 } 1116 1117 /* find the socket in the hmap */ 1118 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1119 if (socket != null) { 1120 if (socket.doGetRemoteSocketMiu() != 0) { 1121 return socket.doGetRemoteSocketMiu(); 1122 } else { 1123 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1124 } 1125 } else { 1126 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1127 } 1128 } 1129 1130 @Override 1131 public int getRemoteSocketRw(int nativeHandle) throws RemoteException { 1132 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1133 1134 NativeLlcpSocket socket = null; 1135 1136 // Check if NFC is enabled 1137 if (!mIsNfcEnabled) { 1138 return ErrorCodes.ERROR_NOT_INITIALIZED; 1139 } 1140 1141 /* find the socket in the hmap */ 1142 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1143 if (socket != null) { 1144 if (socket.doGetRemoteSocketRw() != 0) { 1145 return socket.doGetRemoteSocketRw(); 1146 } else { 1147 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1148 } 1149 } else { 1150 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 1151 } 1152 } 1153 1154 @Override 1155 public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException { 1156 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1157 1158 NativeLlcpSocket socket = null; 1159 int receiveLength = 0; 1160 1161 // Check if NFC is enabled 1162 if (!mIsNfcEnabled) { 1163 return ErrorCodes.ERROR_NOT_INITIALIZED; 1164 } 1165 1166 /* find the socket in the hmap */ 1167 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1168 if (socket != null) { 1169 return socket.doReceive(receiveBuffer); 1170 } else { 1171 return 0; 1172 } 1173 } 1174 1175 @Override 1176 public int send(int nativeHandle, byte[] data) throws RemoteException { 1177 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1178 1179 NativeLlcpSocket socket = null; 1180 boolean isSuccess = false; 1181 1182 // Check if NFC is enabled 1183 if (!mIsNfcEnabled) { 1184 return ErrorCodes.ERROR_NOT_INITIALIZED; 1185 } 1186 1187 /* find the socket in the hmap */ 1188 socket = (NativeLlcpSocket) findSocket(nativeHandle); 1189 if (socket != null) { 1190 isSuccess = socket.doSend(data); 1191 if (isSuccess) { 1192 return ErrorCodes.SUCCESS; 1193 } else { 1194 return ErrorCodes.ERROR_IO; 1195 } 1196 } else { 1197 return ErrorCodes.ERROR_IO; 1198 } 1199 } 1200 }; 1201 1202 private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() { 1203 1204 @Override 1205 public int accept(int nativeHandle) throws RemoteException { 1206 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1207 1208 NativeLlcpServiceSocket socket = null; 1209 NativeLlcpSocket clientSocket = null; 1210 1211 // Check if NFC is enabled 1212 if (!mIsNfcEnabled) { 1213 return ErrorCodes.ERROR_NOT_INITIALIZED; 1214 } 1215 1216 if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { 1217 /* find the socket in the hmap */ 1218 socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); 1219 if (socket != null) { 1220 clientSocket = socket.doAccept(socket.getMiu(), 1221 socket.getRw(), socket.getLinearBufferLength()); 1222 if (clientSocket != null) { 1223 /* Add the socket into the socket map */ 1224 synchronized(this) { 1225 mSocketMap.put(clientSocket.getHandle(), clientSocket); 1226 mNbSocketCreated++; 1227 } 1228 return clientSocket.getHandle(); 1229 } else { 1230 return ErrorCodes.ERROR_IO; 1231 } 1232 } else { 1233 return ErrorCodes.ERROR_IO; 1234 } 1235 } else { 1236 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 1237 } 1238 1239 } 1240 1241 @Override 1242 public void close(int nativeHandle) throws RemoteException { 1243 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1244 1245 NativeLlcpServiceSocket socket = null; 1246 boolean isSuccess = false; 1247 1248 // Check if NFC is enabled 1249 if (!mIsNfcEnabled) { 1250 return; 1251 } 1252 1253 /* find the socket in the hmap */ 1254 boolean closed = false; 1255 socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); 1256 if (socket != null) { 1257 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 1258 isSuccess = socket.doClose(); 1259 if (isSuccess) { 1260 closed = true; 1261 } 1262 } else { 1263 closed = true; 1264 } 1265 } 1266 1267 // If the socket is closed remove it from the socket lists 1268 if (closed) { 1269 synchronized (this) { 1270 /* Remove the socket closed from the hmap */ 1271 RemoveSocket(nativeHandle); 1272 1273 /* Update mNbSocketCreated */ 1274 mNbSocketCreated--; 1275 1276 /* Remove registered socket from the list */ 1277 RemoveRegisteredSocket(nativeHandle); 1278 } 1279 } 1280 } 1281 }; 1282 1283 private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() { 1284 1285 @Override 1286 public void close(int nativeHandle) throws RemoteException { 1287 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1288 1289 NativeLlcpConnectionlessSocket socket = null; 1290 boolean isSuccess = false; 1291 1292 // Check if NFC is enabled 1293 if (!mIsNfcEnabled) { 1294 return; 1295 } 1296 1297 /* find the socket in the hmap */ 1298 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1299 if (socket != null) { 1300 if (mLlcpLinkState == NfcAdapter.LLCP_LINK_STATE_ACTIVATED) { 1301 isSuccess = socket.doClose(); 1302 if (isSuccess) { 1303 /* Remove the socket closed from the hmap */ 1304 RemoveSocket(nativeHandle); 1305 /* Update mNbSocketCreated */ 1306 mNbSocketCreated--; 1307 } 1308 } else { 1309 /* Remove the socket closed from the hmap */ 1310 RemoveSocket(nativeHandle); 1311 1312 /* Remove registered socket from the list */ 1313 RemoveRegisteredSocket(nativeHandle); 1314 1315 /* Update mNbSocketCreated */ 1316 mNbSocketCreated--; 1317 } 1318 } 1319 } 1320 1321 @Override 1322 public int getSap(int nativeHandle) throws RemoteException { 1323 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1324 1325 NativeLlcpConnectionlessSocket socket = null; 1326 1327 // Check if NFC is enabled 1328 if (!mIsNfcEnabled) { 1329 return ErrorCodes.ERROR_NOT_INITIALIZED; 1330 } 1331 1332 /* find the socket in the hmap */ 1333 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1334 if (socket != null) { 1335 return socket.getSap(); 1336 } else { 1337 return 0; 1338 } 1339 } 1340 1341 @Override 1342 public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException { 1343 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1344 1345 NativeLlcpConnectionlessSocket socket = null; 1346 LlcpPacket packet; 1347 1348 // Check if NFC is enabled 1349 if (!mIsNfcEnabled) { 1350 return null; 1351 } 1352 1353 /* find the socket in the hmap */ 1354 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1355 if (socket != null) { 1356 packet = socket.doReceiveFrom(socket.getLinkMiu()); 1357 if (packet != null) { 1358 return packet; 1359 } 1360 return null; 1361 } else { 1362 return null; 1363 } 1364 } 1365 1366 @Override 1367 public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException { 1368 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1369 1370 NativeLlcpConnectionlessSocket socket = null; 1371 boolean isSuccess = false; 1372 1373 // Check if NFC is enabled 1374 if (!mIsNfcEnabled) { 1375 return ErrorCodes.ERROR_NOT_INITIALIZED; 1376 } 1377 1378 /* find the socket in the hmap */ 1379 socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); 1380 if (socket != null) { 1381 isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer()); 1382 if (isSuccess) { 1383 return ErrorCodes.SUCCESS; 1384 } else { 1385 return ErrorCodes.ERROR_IO; 1386 } 1387 } else { 1388 return ErrorCodes.ERROR_IO; 1389 } 1390 } 1391 }; 1392 1393 private final INfcTag mNfcTagService = new INfcTag.Stub() { 1394 1395 @Override 1396 public int close(int nativeHandle) throws RemoteException { 1397 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1398 1399 NativeNfcTag tag = null; 1400 1401 // Check if NFC is enabled 1402 if (!mIsNfcEnabled) { 1403 return ErrorCodes.ERROR_NOT_INITIALIZED; 1404 } 1405 1406 /* find the tag in the hmap */ 1407 tag = (NativeNfcTag) findObject(nativeHandle); 1408 if (tag != null) { 1409 /* Remove the device from the hmap */ 1410 unregisterObject(nativeHandle); 1411 tag.disconnect(); 1412 return ErrorCodes.SUCCESS; 1413 } 1414 /* Restart polling loop for notification */ 1415 maybeEnableDiscovery(); 1416 return ErrorCodes.ERROR_DISCONNECT; 1417 } 1418 1419 @Override 1420 public int connect(int nativeHandle, int technology) throws RemoteException { 1421 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1422 1423 NativeNfcTag tag = null; 1424 1425 // Check if NFC is enabled 1426 if (!mIsNfcEnabled) { 1427 return ErrorCodes.ERROR_NOT_INITIALIZED; 1428 } 1429 1430 /* find the tag in the hmap */ 1431 tag = (NativeNfcTag) findObject(nativeHandle); 1432 if (tag == null) { 1433 return ErrorCodes.ERROR_DISCONNECT; 1434 } 1435 1436 // Note that on most tags, all technologies are behind a single 1437 // handle. This means that the connect at the lower levels 1438 // will do nothing, as the tag is already connected to that handle. 1439 if (tag.connect(technology)) { 1440 return ErrorCodes.SUCCESS; 1441 } else { 1442 return ErrorCodes.ERROR_DISCONNECT; 1443 } 1444 } 1445 1446 @Override 1447 public int reconnect(int nativeHandle) throws RemoteException { 1448 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1449 1450 NativeNfcTag tag = null; 1451 1452 // Check if NFC is enabled 1453 if (!mIsNfcEnabled) { 1454 return ErrorCodes.ERROR_NOT_INITIALIZED; 1455 } 1456 1457 /* find the tag in the hmap */ 1458 tag = (NativeNfcTag) findObject(nativeHandle); 1459 if (tag != null) { 1460 if (tag.reconnect()) { 1461 return ErrorCodes.SUCCESS; 1462 } else { 1463 return ErrorCodes.ERROR_DISCONNECT; 1464 } 1465 } 1466 return ErrorCodes.ERROR_DISCONNECT; 1467 } 1468 1469 @Override 1470 public int[] getTechList(int nativeHandle) throws RemoteException { 1471 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1472 1473 // Check if NFC is enabled 1474 if (!mIsNfcEnabled) { 1475 return null; 1476 } 1477 1478 /* find the tag in the hmap */ 1479 NativeNfcTag tag = (NativeNfcTag) findObject(nativeHandle); 1480 if (tag != null) { 1481 return tag.getTechList(); 1482 } 1483 return null; 1484 } 1485 1486 @Override 1487 public byte[] getUid(int nativeHandle) throws RemoteException { 1488 NativeNfcTag tag = null; 1489 byte[] uid; 1490 1491 // Check if NFC is enabled 1492 if (!mIsNfcEnabled) { 1493 return null; 1494 } 1495 1496 /* find the tag in the hmap */ 1497 tag = (NativeNfcTag) findObject(nativeHandle); 1498 if (tag != null) { 1499 uid = tag.getUid(); 1500 return uid; 1501 } 1502 return null; 1503 } 1504 1505 @Override 1506 public boolean isPresent(int nativeHandle) throws RemoteException { 1507 NativeNfcTag tag = null; 1508 1509 // Check if NFC is enabled 1510 if (!mIsNfcEnabled) { 1511 return false; 1512 } 1513 1514 /* find the tag in the hmap */ 1515 tag = (NativeNfcTag) findObject(nativeHandle); 1516 if (tag == null) { 1517 return false; 1518 } 1519 1520 return tag.presenceCheck(); 1521 } 1522 1523 @Override 1524 public boolean isNdef(int nativeHandle) throws RemoteException { 1525 NativeNfcTag tag = null; 1526 boolean isSuccess = false; 1527 1528 // Check if NFC is enabled 1529 if (!mIsNfcEnabled) { 1530 return isSuccess; 1531 } 1532 1533 /* find the tag in the hmap */ 1534 tag = (NativeNfcTag) findObject(nativeHandle); 1535 int[] ndefInfo = new int[2]; 1536 if (tag != null) { 1537 isSuccess = tag.checkNdef(ndefInfo); 1538 } 1539 return isSuccess; 1540 } 1541 1542 @Override 1543 public byte[] transceive(int nativeHandle, byte[] data, boolean raw) 1544 throws RemoteException { 1545 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1546 1547 NativeNfcTag tag = null; 1548 byte[] response; 1549 1550 // Check if NFC is enabled 1551 if (!mIsNfcEnabled) { 1552 return null; 1553 } 1554 1555 /* find the tag in the hmap */ 1556 tag = (NativeNfcTag) findObject(nativeHandle); 1557 if (tag != null) { 1558 response = tag.transceive(data, raw); 1559 return response; 1560 } 1561 return null; 1562 } 1563 1564 @Override 1565 public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1566 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1567 1568 NativeNfcTag tag; 1569 1570 // Check if NFC is enabled 1571 if (!mIsNfcEnabled) { 1572 return null; 1573 } 1574 1575 /* find the tag in the hmap */ 1576 tag = (NativeNfcTag) findObject(nativeHandle); 1577 if (tag != null) { 1578 byte[] buf = tag.read(); 1579 if (buf == null) 1580 return null; 1581 1582 /* Create an NdefMessage */ 1583 try { 1584 return new NdefMessage(buf); 1585 } catch (FormatException e) { 1586 return null; 1587 } 1588 } 1589 return null; 1590 } 1591 1592 @Override 1593 public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1594 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1595 1596 NativeNfcTag tag; 1597 1598 // Check if NFC is enabled 1599 if (!mIsNfcEnabled) { 1600 return ErrorCodes.ERROR_NOT_INITIALIZED; 1601 } 1602 1603 /* find the tag in the hmap */ 1604 tag = (NativeNfcTag) findObject(nativeHandle); 1605 if (tag == null) { 1606 return ErrorCodes.ERROR_IO; 1607 } 1608 1609 if (tag.write(msg.toByteArray())) { 1610 return ErrorCodes.SUCCESS; 1611 } 1612 else { 1613 return ErrorCodes.ERROR_IO; 1614 } 1615 1616 } 1617 1618 @Override 1619 public int getLastError(int nativeHandle) throws RemoteException { 1620 return(mManager.doGetLastError()); 1621 } 1622 1623 @Override 1624 public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 1625 throw new UnsupportedOperationException(); 1626 } 1627 1628 @Override 1629 public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 1630 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1631 1632 NativeNfcTag tag; 1633 1634 // Check if NFC is enabled 1635 if (!mIsNfcEnabled) { 1636 return ErrorCodes.ERROR_NOT_INITIALIZED; 1637 } 1638 1639 /* find the tag in the hmap */ 1640 tag = (NativeNfcTag) findObject(nativeHandle); 1641 if (tag == null) { 1642 return ErrorCodes.ERROR_IO; 1643 } 1644 1645 if (tag.makeReadonly()) { 1646 return ErrorCodes.SUCCESS; 1647 } 1648 else { 1649 return ErrorCodes.ERROR_IO; 1650 } 1651 } 1652 1653 @Override 1654 public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 1655 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1656 1657 NativeNfcTag tag; 1658 1659 // Check if NFC is enabled 1660 if (!mIsNfcEnabled) { 1661 return ErrorCodes.ERROR_NOT_INITIALIZED; 1662 } 1663 1664 /* find the tag in the hmap */ 1665 tag = (NativeNfcTag) findObject(nativeHandle); 1666 if (tag == null) { 1667 return ErrorCodes.ERROR_IO; 1668 } 1669 1670 if (tag.formatNdef(key)) { 1671 return ErrorCodes.SUCCESS; 1672 } 1673 else { 1674 return ErrorCodes.ERROR_IO; 1675 } 1676 } 1677 1678 1679 }; 1680 1681 private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() { 1682 1683 @Override 1684 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1685 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1686 1687 NativeP2pDevice device; 1688 1689 // Check if NFC is enabled 1690 if (!mIsNfcEnabled) { 1691 return null; 1692 } 1693 1694 /* find the device in the hmap */ 1695 device = (NativeP2pDevice) findObject(nativeHandle); 1696 if (device != null) { 1697 byte[] buff = device.getGeneralBytes(); 1698 if (buff == null) 1699 return null; 1700 return buff; 1701 } 1702 return null; 1703 } 1704 1705 @Override 1706 public int getMode(int nativeHandle) throws RemoteException { 1707 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1708 1709 NativeP2pDevice device; 1710 1711 // Check if NFC is enabled 1712 if (!mIsNfcEnabled) { 1713 return ErrorCodes.ERROR_NOT_INITIALIZED; 1714 } 1715 1716 /* find the device in the hmap */ 1717 device = (NativeP2pDevice) findObject(nativeHandle); 1718 if (device != null) { 1719 return device.getMode(); 1720 } 1721 return ErrorCodes.ERROR_INVALID_PARAM; 1722 } 1723 1724 @Override 1725 public byte[] receive(int nativeHandle) throws RemoteException { 1726 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1727 1728 NativeP2pDevice device; 1729 1730 // Check if NFC is enabled 1731 if (!mIsNfcEnabled) { 1732 return null; 1733 } 1734 1735 /* find the device in the hmap */ 1736 device = (NativeP2pDevice) findObject(nativeHandle); 1737 if (device != null) { 1738 byte[] buff = device.doReceive(); 1739 if (buff == null) 1740 return null; 1741 return buff; 1742 } 1743 /* Restart polling loop for notification */ 1744 maybeEnableDiscovery(); 1745 return null; 1746 } 1747 1748 @Override 1749 public boolean send(int nativeHandle, byte[] data) throws RemoteException { 1750 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1751 1752 NativeP2pDevice device; 1753 boolean isSuccess = false; 1754 1755 // Check if NFC is enabled 1756 if (!mIsNfcEnabled) { 1757 return isSuccess; 1758 } 1759 1760 /* find the device in the hmap */ 1761 device = (NativeP2pDevice) findObject(nativeHandle); 1762 if (device != null) { 1763 isSuccess = device.doSend(data); 1764 } 1765 return isSuccess; 1766 } 1767 }; 1768 1769 private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() { 1770 1771 @Override 1772 public int connect(int nativeHandle) throws RemoteException { 1773 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1774 1775 NativeP2pDevice device; 1776 1777 // Check if NFC is enabled 1778 if (!mIsNfcEnabled) { 1779 return ErrorCodes.ERROR_NOT_INITIALIZED; 1780 } 1781 1782 /* find the device in the hmap */ 1783 device = (NativeP2pDevice) findObject(nativeHandle); 1784 if (device != null) { 1785 if (device.doConnect()) { 1786 return ErrorCodes.SUCCESS; 1787 } 1788 } 1789 return ErrorCodes.ERROR_CONNECT; 1790 } 1791 1792 @Override 1793 public boolean disconnect(int nativeHandle) throws RemoteException { 1794 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1795 1796 NativeP2pDevice device; 1797 boolean isSuccess = false; 1798 1799 // Check if NFC is enabled 1800 if (!mIsNfcEnabled) { 1801 return isSuccess; 1802 } 1803 1804 /* find the device in the hmap */ 1805 device = (NativeP2pDevice) findObject(nativeHandle); 1806 if (device != null) { 1807 if (isSuccess = device.doDisconnect()) { 1808 /* remove the device from the hmap */ 1809 unregisterObject(nativeHandle); 1810 /* Restart polling loop for notification */ 1811 maybeEnableDiscovery(); 1812 } 1813 } 1814 return isSuccess; 1815 1816 } 1817 1818 @Override 1819 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1820 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1821 1822 NativeP2pDevice device; 1823 1824 // Check if NFC is enabled 1825 if (!mIsNfcEnabled) { 1826 return null; 1827 } 1828 1829 /* find the device in the hmap */ 1830 device = (NativeP2pDevice) findObject(nativeHandle); 1831 if (device != null) { 1832 byte[] buff = device.getGeneralBytes(); 1833 if (buff == null) 1834 return null; 1835 return buff; 1836 } 1837 return null; 1838 } 1839 1840 @Override 1841 public int getMode(int nativeHandle) throws RemoteException { 1842 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1843 1844 NativeP2pDevice device; 1845 1846 // Check if NFC is enabled 1847 if (!mIsNfcEnabled) { 1848 return ErrorCodes.ERROR_NOT_INITIALIZED; 1849 } 1850 1851 /* find the device in the hmap */ 1852 device = (NativeP2pDevice) findObject(nativeHandle); 1853 if (device != null) { 1854 return device.getMode(); 1855 } 1856 return ErrorCodes.ERROR_INVALID_PARAM; 1857 } 1858 1859 @Override 1860 public byte[] transceive(int nativeHandle, byte[] data) 1861 throws RemoteException { 1862 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1863 1864 NativeP2pDevice device; 1865 1866 // Check if NFC is enabled 1867 if (!mIsNfcEnabled) { 1868 return null; 1869 } 1870 1871 /* find the device in the hmap */ 1872 device = (NativeP2pDevice) findObject(nativeHandle); 1873 if (device != null) { 1874 byte[] buff = device.doTransceive(data); 1875 if (buff == null) 1876 return null; 1877 return buff; 1878 } 1879 return null; 1880 } 1881 }; 1882 1883 private INfcSecureElement mSecureElementService = new INfcSecureElement.Stub() { 1884 1885 public int openSecureElementConnection() throws RemoteException { 1886 Log.d(TAG, "openSecureElementConnection"); 1887 int handle; 1888 1889 // Check if NFC is enabled 1890 if (!mIsNfcEnabled) { 1891 return 0; 1892 } 1893 1894 // Check in an open is already pending 1895 if (mOpenSmxPending) { 1896 return 0; 1897 } 1898 1899 handle = mSecureElement.doOpenSecureElementConnection(); 1900 1901 if (handle == 0) { 1902 mOpenSmxPending = false; 1903 } else { 1904 mSecureElementHandle = handle; 1905 1906 /* Start timer */ 1907 mTimerOpenSmx = new Timer(); 1908 mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000); 1909 1910 /* Update state */ 1911 isOpened = true; 1912 isClosed = false; 1913 mOpenSmxPending = true; 1914 } 1915 1916 return handle; 1917 } 1918 1919 public int closeSecureElementConnection(int nativeHandle) 1920 throws RemoteException { 1921 1922 // Check if NFC is enabled 1923 if (!mIsNfcEnabled) { 1924 return ErrorCodes.ERROR_NOT_INITIALIZED; 1925 } 1926 1927 // Check if the SE connection is closed 1928 if (isClosed) { 1929 return -1; 1930 } 1931 1932 // Check if the SE connection is opened 1933 if (!isOpened) { 1934 return -1; 1935 } 1936 1937 if (mSecureElement.doDisconnect(nativeHandle)) { 1938 1939 /* Stop timer */ 1940 mTimerOpenSmx.cancel(); 1941 1942 /* Restart polling loop for notification */ 1943 mManager.enableDiscovery(DISCOVERY_MODE_READER); 1944 1945 /* Update state */ 1946 isOpened = false; 1947 isClosed = true; 1948 mOpenSmxPending = false; 1949 1950 return ErrorCodes.SUCCESS; 1951 } else { 1952 1953 /* Stop timer */ 1954 mTimerOpenSmx.cancel(); 1955 1956 /* Restart polling loop for notification */ 1957 mManager.enableDiscovery(DISCOVERY_MODE_READER); 1958 1959 /* Update state */ 1960 isOpened = false; 1961 isClosed = true; 1962 mOpenSmxPending = false; 1963 1964 return ErrorCodes.ERROR_DISCONNECT; 1965 } 1966 } 1967 1968 public int[] getSecureElementTechList(int nativeHandle) 1969 throws RemoteException { 1970 // Check if NFC is enabled 1971 if (!mIsNfcEnabled) { 1972 return null; 1973 } 1974 1975 // Check if the SE connection is closed 1976 if (isClosed) { 1977 return null; 1978 } 1979 1980 // Check if the SE connection is opened 1981 if (!isOpened) { 1982 return null; 1983 } 1984 1985 int[] techList = mSecureElement.doGetTechList(nativeHandle); 1986 1987 /* Stop and Restart timer */ 1988 mTimerOpenSmx.cancel(); 1989 mTimerOpenSmx = new Timer(); 1990 mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000); 1991 1992 return techList; 1993 } 1994 1995 public byte[] getSecureElementUid(int nativeHandle) 1996 throws RemoteException { 1997 byte[] uid; 1998 1999 // Check if NFC is enabled 2000 if (!mIsNfcEnabled) { 2001 return null; 2002 } 2003 2004 // Check if the SE connection is closed 2005 if (isClosed) { 2006 return null; 2007 } 2008 2009 // Check if the SE connection is opened 2010 if (!isOpened) { 2011 return null; 2012 } 2013 2014 uid = mSecureElement.doGetUid(nativeHandle); 2015 2016 /* Stop and Restart timer */ 2017 mTimerOpenSmx.cancel(); 2018 mTimerOpenSmx = new Timer(); 2019 mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000); 2020 2021 return uid; 2022 } 2023 2024 public byte[] exchangeAPDU(int nativeHandle, byte[] data) 2025 throws RemoteException { 2026 byte[] response; 2027 2028 // Check if NFC is enabled 2029 if (!mIsNfcEnabled) { 2030 return null; 2031 } 2032 2033 // Check if the SE connection is closed 2034 if (isClosed) { 2035 return null; 2036 } 2037 2038 // Check if the SE connection is opened 2039 if (!isOpened) { 2040 return null; 2041 } 2042 2043 response = mSecureElement.doTransceive(nativeHandle, data); 2044 2045 /* Stop and Restart timer */ 2046 mTimerOpenSmx.cancel(); 2047 mTimerOpenSmx = new Timer(); 2048 mTimerOpenSmx.schedule(new TimerOpenSecureElement(), 30000); 2049 2050 return response; 2051 2052 } 2053 }; 2054 2055 class TimerOpenSecureElement extends TimerTask { 2056 2057 @Override 2058 public void run() { 2059 if (mSecureElementHandle != 0) { 2060 Log.d(TAG, "Open SMX timer expired"); 2061 try { 2062 mSecureElementService 2063 .closeSecureElementConnection(mSecureElementHandle); 2064 } catch (RemoteException e) { 2065 } 2066 } 2067 2068 } 2069 2070 } 2071 2072 private boolean _enable(boolean oldEnabledState) { 2073 boolean isSuccess = mManager.initialize(); 2074 if (isSuccess) { 2075 applyProperties(); 2076 2077 /* Check Secure Element setting */ 2078 mNfcSecureElementState = mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON, 2079 SECURE_ELEMENT_ON_DEFAULT); 2080 2081 if (mNfcSecureElementState) { 2082 int secureElementId = mPrefs.getInt(PREF_SECURE_ELEMENT_ID, 2083 SECURE_ELEMENT_ID_DEFAULT); 2084 int[] Se_list = mManager.doGetSecureElementList(); 2085 if (Se_list != null) { 2086 for (int i = 0; i < Se_list.length; i++) { 2087 if (Se_list[i] == secureElementId) { 2088 mManager.doSelectSecureElement(Se_list[i]); 2089 mSelectedSeId = Se_list[i]; 2090 break; 2091 } 2092 } 2093 } 2094 } 2095 2096 mIsNfcEnabled = true; 2097 2098 /* Start polling loop */ 2099 maybeEnableDiscovery(); 2100 2101 /* bring up the my tag server */ 2102 mMyTagServer.start(); 2103 2104 } else { 2105 mIsNfcEnabled = false; 2106 } 2107 2108 updateNfcOnSetting(oldEnabledState); 2109 2110 return isSuccess; 2111 } 2112 2113 /** Enable active tag discovery if screen is on and NFC is enabled */ 2114 private synchronized void maybeEnableDiscovery() { 2115 if (mScreenOn && mIsNfcEnabled) { 2116 mManager.enableDiscovery(DISCOVERY_MODE_READER); 2117 } 2118 } 2119 2120 /** Disable active tag discovery if necessary */ 2121 private synchronized void maybeDisableDiscovery() { 2122 if (mIsNfcEnabled) { 2123 mManager.disableDiscovery(); 2124 } 2125 } 2126 2127 private void applyProperties() { 2128 mManager.doSetProperties(PROPERTY_LLCP_LTO, mPrefs.getInt(PREF_LLCP_LTO, LLCP_LTO_DEFAULT)); 2129 mManager.doSetProperties(PROPERTY_LLCP_MIU, mPrefs.getInt(PREF_LLCP_MIU, LLCP_MIU_DEFAULT)); 2130 mManager.doSetProperties(PROPERTY_LLCP_WKS, mPrefs.getInt(PREF_LLCP_WKS, LLCP_WKS_DEFAULT)); 2131 mManager.doSetProperties(PROPERTY_LLCP_OPT, mPrefs.getInt(PREF_LLCP_OPT, LLCP_OPT_DEFAULT)); 2132 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, 2133 mPrefs.getBoolean(PREF_DISCOVERY_A, DISCOVERY_A_DEFAULT) ? 1 : 0); 2134 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, 2135 mPrefs.getBoolean(PREF_DISCOVERY_B, DISCOVERY_B_DEFAULT) ? 1 : 0); 2136 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, 2137 mPrefs.getBoolean(PREF_DISCOVERY_F, DISCOVERY_F_DEFAULT) ? 1 : 0); 2138 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, 2139 mPrefs.getBoolean(PREF_DISCOVERY_15693, DISCOVERY_15693_DEFAULT) ? 1 : 0); 2140 mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, 2141 mPrefs.getBoolean(PREF_DISCOVERY_NFCIP, DISCOVERY_NFCIP_DEFAULT) ? 1 : 0); 2142 } 2143 2144 private void updateNfcOnSetting(boolean oldEnabledState) { 2145 int state; 2146 2147 mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled); 2148 mPrefsEditor.apply(); 2149 2150 synchronized(this) { 2151 if (oldEnabledState != mIsNfcEnabled) { 2152 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE); 2153 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2154 intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled); 2155 mContext.sendBroadcast(intent); 2156 } 2157 2158 if (mIsNfcEnabled) { 2159 2160 Context context = getApplicationContext(); 2161 2162 // Set this to null by default. If there isn't a tag on disk 2163 // or if there was an error reading the tag then this will cause 2164 // the status bar icon to be removed. 2165 NdefMessage myTag = null; 2166 2167 FileInputStream input = null; 2168 2169 try { 2170 input = context.openFileInput(MY_TAG_FILE_NAME); 2171 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 2172 2173 byte[] buffer = new byte[4096]; 2174 int read = 0; 2175 while ((read = input.read(buffer)) > 0) { 2176 bytes.write(buffer, 0, read); 2177 } 2178 2179 myTag = new NdefMessage(bytes.toByteArray()); 2180 } catch (FileNotFoundException e) { 2181 // Ignore. 2182 } catch (IOException e) { 2183 Log.e(TAG, "Could not read mytag file: ", e); 2184 context.deleteFile(MY_TAG_FILE_NAME); 2185 } catch (FormatException e) { 2186 Log.e(TAG, "Invalid NdefMessage for mytag", e); 2187 context.deleteFile(MY_TAG_FILE_NAME); 2188 } finally { 2189 try { 2190 if (input != null) { 2191 input.close(); 2192 } 2193 } catch (IOException e) { 2194 // Ignore 2195 } 2196 } 2197 2198 try { 2199 mNfcAdapter.localSet(myTag); 2200 } catch (RemoteException e) { 2201 // Ignore 2202 } 2203 } else { 2204 sendMessage(MSG_HIDE_MY_TAG_ICON, null); 2205 } 2206 } 2207 } 2208 2209 // Reset all internals 2210 private synchronized void reset() { 2211 // TODO: none of these appear to be synchronized but are 2212 // read/written from different threads (notably Binder threads)... 2213 2214 // Clear tables 2215 mObjectMap.clear(); 2216 mSocketMap.clear(); 2217 mRegisteredSocketList.clear(); 2218 2219 // Reset variables 2220 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 2221 mNbSocketCreated = 0; 2222 mIsNfcEnabled = false; 2223 mSelectedSeId = 0; 2224 } 2225 2226 private synchronized Object findObject(int key) { 2227 Object device = null; 2228 2229 device = mObjectMap.get(key); 2230 if (device == null) { 2231 Log.w(TAG, "Handle not found !"); 2232 } 2233 2234 return device; 2235 } 2236 2237 synchronized void registerTagObject(NativeNfcTag nativeTag) { 2238 mObjectMap.put(nativeTag.getHandle(), nativeTag); 2239 } 2240 2241 synchronized void unregisterObject(int handle) { 2242 mObjectMap.remove(handle); 2243 } 2244 2245 private synchronized Object findSocket(int key) { 2246 Object socket = null; 2247 2248 socket = mSocketMap.get(key); 2249 2250 return socket; 2251 } 2252 2253 private void RemoveSocket(int key) { 2254 mSocketMap.remove(key); 2255 } 2256 2257 private boolean CheckSocketSap(int sap) { 2258 /* List of sockets registered */ 2259 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 2260 2261 while (it.hasNext()) { 2262 RegisteredSocket registeredSocket = it.next(); 2263 2264 if (sap == registeredSocket.mSap) { 2265 /* SAP already used */ 2266 return false; 2267 } 2268 } 2269 return true; 2270 } 2271 2272 private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) { 2273 2274 if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT || linearBufferlength < miu) { 2275 return false; 2276 } 2277 return true; 2278 } 2279 2280 private boolean CheckSocketServiceName(String sn) { 2281 2282 /* List of sockets registered */ 2283 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 2284 2285 while (it.hasNext()) { 2286 RegisteredSocket registeredSocket = it.next(); 2287 2288 if (sn.equals(registeredSocket.mServiceName)) { 2289 /* Service Name already used */ 2290 return false; 2291 } 2292 } 2293 return true; 2294 } 2295 2296 private void RemoveRegisteredSocket(int nativeHandle) { 2297 /* check if sockets are registered */ 2298 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 2299 2300 while (it.hasNext()) { 2301 RegisteredSocket registeredSocket = it.next(); 2302 if (registeredSocket.mHandle == nativeHandle) { 2303 /* remove the registered socket from the list */ 2304 it.remove(); 2305 if (DBG) Log.d(TAG, "socket removed"); 2306 } 2307 } 2308 } 2309 2310 /* 2311 * RegisteredSocket class to store the creation request of socket until the 2312 * LLCP link in not activated 2313 */ 2314 private class RegisteredSocket { 2315 private final int mType; 2316 2317 private final int mHandle; 2318 2319 private final int mSap; 2320 2321 private int mMiu; 2322 2323 private int mRw; 2324 2325 private String mServiceName; 2326 2327 private int mlinearBufferLength; 2328 2329 RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw, 2330 int linearBufferLength) { 2331 mType = type; 2332 mHandle = handle; 2333 mSap = sap; 2334 mServiceName = sn; 2335 mRw = rw; 2336 mMiu = miu; 2337 mlinearBufferLength = linearBufferLength; 2338 } 2339 2340 RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) { 2341 mType = type; 2342 mHandle = handle; 2343 mSap = sap; 2344 mRw = rw; 2345 mMiu = miu; 2346 mlinearBufferLength = linearBufferLength; 2347 } 2348 2349 RegisteredSocket(int type, int handle, int sap) { 2350 mType = type; 2351 mHandle = handle; 2352 mSap = sap; 2353 } 2354 } 2355 2356 /** For use by code in this process */ 2357 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) { 2358 try { 2359 int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength); 2360 if (ErrorCodes.isError(handle)) { 2361 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2362 return null; 2363 } 2364 return new LlcpSocket(mLlcpSocket, handle); 2365 } catch (RemoteException e) { 2366 // This will never happen since the code is calling into it's own process 2367 throw new IllegalStateException("unable to talk to myself", e); 2368 } 2369 } 2370 2371 /** For use by code in this process */ 2372 public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw, 2373 int linearBufferLength) { 2374 try { 2375 int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 2376 if (ErrorCodes.isError(handle)) { 2377 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2378 return null; 2379 } 2380 return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle); 2381 } catch (RemoteException e) { 2382 // This will never happen since the code is calling into it's own process 2383 throw new IllegalStateException("unable to talk to myself", e); 2384 } 2385 } 2386 2387 private void activateLlcpLink() { 2388 /* check if sockets are registered */ 2389 ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator(); 2390 2391 if (DBG) Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size()); 2392 2393 /* Mark the link state */ 2394 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_ACTIVATED; 2395 2396 while (it.hasNext()) { 2397 RegisteredSocket registeredSocket = it.next(); 2398 2399 switch (registeredSocket.mType) { 2400 case LLCP_SERVICE_SOCKET_TYPE: 2401 if (DBG) Log.d(TAG, "Registered Llcp Service Socket"); 2402 if (DBG) Log.d(TAG, "SAP: " + registeredSocket.mSap + ", SN: " + registeredSocket.mServiceName); 2403 NativeLlcpServiceSocket serviceSocket; 2404 2405 serviceSocket = mManager.doCreateLlcpServiceSocket( 2406 registeredSocket.mSap, registeredSocket.mServiceName, 2407 registeredSocket.mMiu, registeredSocket.mRw, 2408 registeredSocket.mlinearBufferLength); 2409 2410 if (serviceSocket != null) { 2411 if (DBG) Log.d(TAG, "service socket created"); 2412 /* Add the socket into the socket map */ 2413 synchronized(NfcService.this) { 2414 mSocketMap.put(registeredSocket.mHandle, serviceSocket); 2415 } 2416 } else { 2417 Log.d(TAG, "FAILED to create service socket"); 2418 /* socket creation error - update the socket 2419 * handle counter */ 2420 mGeneratedSocketHandle -= 1; 2421 } 2422 2423 // NOTE: don't remove this socket from the registered sockets list. 2424 // If it's removed it won't be created the next time an LLCP 2425 // connection is activated and the server won't be found. 2426 break; 2427 2428 case LLCP_SOCKET_TYPE: 2429 if (DBG) Log.d(TAG, "Registered Llcp Socket"); 2430 NativeLlcpSocket clientSocket; 2431 clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap, 2432 registeredSocket.mMiu, registeredSocket.mRw, 2433 registeredSocket.mlinearBufferLength); 2434 if (clientSocket != null) { 2435 if (DBG) Log.d(TAG, "socket created"); 2436 /* Add the socket into the socket map */ 2437 synchronized(NfcService.this) { 2438 mSocketMap.put(registeredSocket.mHandle, clientSocket); 2439 } 2440 } else { 2441 Log.d(TAG, "FAILED to create service socket"); 2442 /* socket creation error - update the socket 2443 * handle counter */ 2444 mGeneratedSocketHandle -= 1; 2445 } 2446 // This socket has been created, remove it from the registered sockets list. 2447 it.remove(); 2448 break; 2449 2450 case LLCP_CONNECTIONLESS_SOCKET_TYPE: 2451 if (DBG) Log.d(TAG, "Registered Llcp Connectionless Socket"); 2452 NativeLlcpConnectionlessSocket connectionlessSocket; 2453 connectionlessSocket = mManager.doCreateLlcpConnectionlessSocket( 2454 registeredSocket.mSap); 2455 if (connectionlessSocket != null) { 2456 if (DBG) Log.d(TAG, "connectionless socket created"); 2457 /* Add the socket into the socket map */ 2458 synchronized(NfcService.this) { 2459 mSocketMap.put(registeredSocket.mHandle, connectionlessSocket); 2460 } 2461 } else { 2462 Log.d(TAG, "FAILED to create service socket"); 2463 /* socket creation error - update the socket 2464 * handle counter */ 2465 mGeneratedSocketHandle -= 1; 2466 } 2467 // This socket has been created, remove it from the registered sockets list. 2468 it.remove(); 2469 break; 2470 } 2471 } 2472 2473 /* Broadcast Intent Link LLCP activated */ 2474 Intent LlcpLinkIntent = new Intent(); 2475 LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED); 2476 2477 LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED, 2478 NfcAdapter.LLCP_LINK_STATE_ACTIVATED); 2479 2480 if (DBG) Log.d(TAG, "Broadcasting LLCP activation"); 2481 mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM); 2482 } 2483 2484 public void sendMockNdefTag(NdefMessage msg) { 2485 sendMessage(MSG_MOCK_NDEF, msg); 2486 } 2487 2488 void sendMessage(int what, Object obj) { 2489 Message msg = mHandler.obtainMessage(); 2490 msg.what = what; 2491 msg.obj = obj; 2492 mHandler.sendMessage(msg); 2493 } 2494 2495 final class NfcServiceHandler extends Handler { 2496 2497 public NdefMessage[] findAndReadNdef(NativeNfcTag nativeTag) { 2498 // Try to find NDEF on any of the technologies. 2499 int[] technologies = nativeTag.getTechList(); 2500 int[] handles = nativeTag.getHandleList(); 2501 int techIndex = 0; 2502 int lastHandleScanned = 0; 2503 boolean ndefFoundAndConnected = false; 2504 NdefMessage[] ndefMsgs = null; 2505 2506 while ((!ndefFoundAndConnected) && (techIndex < technologies.length)) { 2507 if (handles[techIndex] != lastHandleScanned) { 2508 // We haven't seen this handle yet, connect and checkndef 2509 if (nativeTag.connect(technologies[techIndex])) { 2510 int[] ndefinfo = new int[2]; 2511 if (nativeTag.checkNdef(ndefinfo)) { 2512 ndefFoundAndConnected = true; 2513 boolean generateEmptyNdef = false; 2514 2515 int supportedNdefLength = ndefinfo[0]; 2516 int cardState = ndefinfo[1]; 2517 byte[] buff = nativeTag.read(); 2518 if (buff != null) { 2519 ndefMsgs = new NdefMessage[1]; 2520 try { 2521 ndefMsgs[0] = new NdefMessage(buff); 2522 nativeTag.addNdefTechnology(ndefMsgs[0], 2523 nativeTag.getConnectedHandle(), 2524 nativeTag.getConnectedLibNfcType(), 2525 supportedNdefLength, cardState); 2526 nativeTag.reconnect(); 2527 } catch (FormatException e) { 2528 // Create an intent anyway, without NDEF messages 2529 generateEmptyNdef = true; 2530 } 2531 } else { 2532 generateEmptyNdef = true; 2533 } 2534 2535 if (generateEmptyNdef) { 2536 ndefMsgs = new NdefMessage[] { }; 2537 nativeTag.addNdefTechnology(null, 2538 nativeTag.getConnectedHandle(), 2539 nativeTag.getConnectedLibNfcType(), 2540 supportedNdefLength, cardState); 2541 nativeTag.reconnect(); 2542 } 2543 } // else, no NDEF on this tech, continue loop 2544 } else { 2545 // Connect failed, tag maybe lost. Try next handle 2546 // anyway. 2547 } 2548 } 2549 lastHandleScanned = handles[techIndex]; 2550 techIndex++; 2551 } 2552 2553 return ndefMsgs; 2554 } 2555 2556 @Override 2557 public void handleMessage(Message msg) { 2558 switch (msg.what) { 2559 case MSG_MOCK_NDEF: { 2560 NdefMessage ndefMsg = (NdefMessage) msg.obj; 2561 Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 2562 new int[] { }, 2563 new Bundle[] { }); 2564 Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 2565 Log.d(TAG, tag.toString()); 2566 dispatchTag(tag, new NdefMessage[] { ndefMsg }); 2567 break; 2568 } 2569 2570 case MSG_NDEF_TAG: 2571 if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 2572 NativeNfcTag nativeTag = (NativeNfcTag) msg.obj; 2573 NdefMessage[] ndefMsgs = findAndReadNdef(nativeTag); 2574 2575 if (ndefMsgs != null) { 2576 dispatchNativeTag(nativeTag, ndefMsgs); 2577 } else { 2578 // No ndef found or connect failed, just try to reconnect and dispatch 2579 if (nativeTag.reconnect()) { 2580 dispatchNativeTag(nativeTag, null); 2581 } else { 2582 Log.w(TAG, "Failed to connect to tag"); 2583 nativeTag.disconnect(); 2584 } 2585 } 2586 break; 2587 2588 case MSG_CARD_EMULATION: 2589 if (DBG) Log.d(TAG, "Card Emulation message"); 2590 byte[] aid = (byte[]) msg.obj; 2591 /* Send broadcast ordered */ 2592 Intent TransactionIntent = new Intent(); 2593 TransactionIntent.setAction(NfcAdapter.ACTION_TRANSACTION_DETECTED); 2594 TransactionIntent.putExtra(NfcAdapter.EXTRA_AID, aid); 2595 if (DBG) Log.d(TAG, "Broadcasting Card Emulation event"); 2596 mContext.sendOrderedBroadcast(TransactionIntent, NFC_PERM); 2597 break; 2598 2599 case MSG_LLCP_LINK_ACTIVATION: 2600 NativeP2pDevice device = (NativeP2pDevice) msg.obj; 2601 2602 Log.d(TAG, "LLCP Activation message"); 2603 2604 if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) { 2605 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 2606 if (device.doConnect()) { 2607 /* Check Llcp compliancy */ 2608 if (mManager.doCheckLlcp()) { 2609 /* Activate Llcp Link */ 2610 if (mManager.doActivateLlcp()) { 2611 if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 2612 activateLlcpLink(); 2613 } else { 2614 /* should not happen */ 2615 Log.w(TAG, "Initiator Activate LLCP NOK. Disconnect."); 2616 device.doDisconnect(); 2617 } 2618 2619 } else { 2620 if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 2621 device.doDisconnect(); 2622 } 2623 } else { 2624 if (DBG) Log.d(TAG, "Cannot connect remote Target. Restart polling loop."); 2625 device.doDisconnect(); 2626 } 2627 2628 } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) { 2629 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 2630 /* Check Llcp compliancy */ 2631 if (mManager.doCheckLlcp()) { 2632 /* Activate Llcp Link */ 2633 if (mManager.doActivateLlcp()) { 2634 if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 2635 activateLlcpLink(); 2636 } 2637 } else { 2638 Log.w(TAG, "checkLlcp failed"); 2639 } 2640 } 2641 break; 2642 2643 case MSG_LLCP_LINK_DEACTIVATED: 2644 device = (NativeP2pDevice) msg.obj; 2645 2646 /* Mark the link state */ 2647 mLlcpLinkState = NfcAdapter.LLCP_LINK_STATE_DEACTIVATED; 2648 2649 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 2650 if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) { 2651 if (DBG) Log.d(TAG, "disconnecting from target"); 2652 /* Restart polling loop */ 2653 device.doDisconnect(); 2654 } else { 2655 if (DBG) Log.d(TAG, "not disconnecting from initiator"); 2656 } 2657 2658 /* Broadcast Intent Link LLCP activated */ 2659 Intent LlcpLinkIntent = new Intent(); 2660 LlcpLinkIntent.setAction(NfcAdapter.ACTION_LLCP_LINK_STATE_CHANGED); 2661 LlcpLinkIntent.putExtra(NfcAdapter.EXTRA_LLCP_LINK_STATE_CHANGED, 2662 NfcAdapter.LLCP_LINK_STATE_DEACTIVATED); 2663 if (DBG) Log.d(TAG, "Broadcasting LLCP deactivation"); 2664 mContext.sendOrderedBroadcast(LlcpLinkIntent, NFC_PERM); 2665 break; 2666 2667 case MSG_TARGET_DESELECTED: 2668 /* Broadcast Intent Target Deselected */ 2669 if (DBG) Log.d(TAG, "Target Deselected"); 2670 Intent TargetDeselectedIntent = new Intent(); 2671 TargetDeselectedIntent.setAction(mManager.INTERNAL_TARGET_DESELECTED_ACTION); 2672 if (DBG) Log.d(TAG, "Broadcasting Intent"); 2673 mContext.sendOrderedBroadcast(TargetDeselectedIntent, NFC_PERM); 2674 break; 2675 2676 case MSG_SHOW_MY_TAG_ICON: { 2677 StatusBarManager sb = (StatusBarManager) getSystemService( 2678 Context.STATUS_BAR_SERVICE); 2679 sb.setIcon("nfc", R.drawable.stat_sys_nfc, 0); 2680 break; 2681 } 2682 2683 case MSG_HIDE_MY_TAG_ICON: { 2684 StatusBarManager sb = (StatusBarManager) getSystemService( 2685 Context.STATUS_BAR_SERVICE); 2686 sb.removeIcon("nfc"); 2687 break; 2688 } 2689 2690 default: 2691 Log.e(TAG, "Unknown message received"); 2692 break; 2693 } 2694 } 2695 2696 private Intent buildTagIntent(Tag tag, NdefMessage[] msgs, String action) { 2697 Intent intent = new Intent(action); 2698 intent.putExtra(NfcAdapter.EXTRA_TAG, tag); 2699 intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId()); 2700 intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, msgs); 2701 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2702 return intent; 2703 } 2704 2705 private void dispatchNativeTag(NativeNfcTag nativeTag, NdefMessage[] msgs) { 2706 Tag tag = new Tag(nativeTag.getUid(), nativeTag.getTechList(), 2707 nativeTag.getTechExtras(), nativeTag.getHandle()); 2708 if (dispatchTag(tag, msgs)) { 2709 registerTagObject(nativeTag); 2710 } else { 2711 nativeTag.disconnect(); 2712 } 2713 } 2714 2715 public byte[] concat(byte[]... arrays) { 2716 int length = 0; 2717 for (byte[] array : arrays) { 2718 length += array.length; 2719 } 2720 byte[] result = new byte[length]; 2721 int pos = 0; 2722 for (byte[] array : arrays) { 2723 System.arraycopy(array, 0, result, pos, array.length); 2724 pos += array.length; 2725 } 2726 return result; 2727 } 2728 2729 private Uri parseWellKnownUriRecord(NdefRecord record) { 2730 byte[] payload = record.getPayload(); 2731 2732 /* 2733 * payload[0] contains the URI Identifier Code, per the 2734 * NFC Forum "URI Record Type Definition" section 3.2.2. 2735 * 2736 * payload[1]...payload[payload.length - 1] contains the rest of 2737 * the URI. 2738 */ 2739 String prefix = URI_PREFIX_MAP[(payload[0] & 0xff)]; 2740 byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8), 2741 Arrays.copyOfRange(payload, 1, payload.length)); 2742 return Uri.parse(new String(fullUri, Charsets.UTF_8)); 2743 } 2744 2745 private boolean setTypeOrDataFromNdef(Intent intent, NdefRecord record) { 2746 short tnf = record.getTnf(); 2747 byte[] type = record.getType(); 2748 switch (tnf) { 2749 case NdefRecord.TNF_MIME_MEDIA: { 2750 intent.setType(new String(type, Charsets.US_ASCII)); 2751 return true; 2752 } 2753 case NdefRecord.TNF_ABSOLUTE_URI: { 2754 intent.setData(Uri.parse(new String(type, Charsets.UTF_8))); 2755 return true; 2756 } 2757 case NdefRecord.TNF_WELL_KNOWN: { 2758 if (Arrays.equals(type, NdefRecord.RTD_TEXT)) { 2759 intent.setType("text/plain"); 2760 return true; 2761 } else if (Arrays.equals(type, NdefRecord.RTD_SMART_POSTER)) { 2762 // Parse the smart poster looking for the URI 2763 try { 2764 NdefMessage msg = new NdefMessage(record.getPayload()); 2765 for (NdefRecord subRecord : msg.getRecords()) { 2766 if (subRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN 2767 && Arrays.equals(subRecord.getType(), NdefRecord.RTD_URI)) { 2768 intent.setData(parseWellKnownUriRecord(subRecord)); 2769 return true; 2770 } 2771 } 2772 } catch (FormatException e) { 2773 return false; 2774 } 2775 } else if (Arrays.equals(type, NdefRecord.RTD_URI)) { 2776 intent.setData(parseWellKnownUriRecord(record)); 2777 return true; 2778 } 2779 return false; 2780 } 2781 } 2782 return false; 2783 } 2784 2785 private Uri buildTechListUri(Tag tag) { 2786 int[] techList = tag.getTechnologyList(); 2787 Arrays.sort(techList); 2788 Uri.Builder builder = new Uri.Builder(); 2789 builder.scheme("vnd.android.nfc").authority("tag"); 2790 for (int tech : techList) { 2791 builder.appendPath(Integer.toString(tech)); 2792 } 2793 builder.appendPath(""); 2794 return builder.build(); 2795 } 2796 2797 /** Returns false if no activities were found to dispatch to */ 2798 private boolean dispatchTag(Tag tag, NdefMessage[] msgs) { 2799 if (DBG) { 2800 Log.d(TAG, "Dispatching tag"); 2801 Log.d(TAG, tag.toString()); 2802 } 2803 2804 Intent intent; 2805 if (msgs != null && msgs.length > 0) { 2806 NdefMessage msg = msgs[0]; 2807 NdefRecord[] records = msg.getRecords(); 2808 if (records.length > 0) { 2809 // Found valid NDEF data, try to dispatch that first 2810 NdefRecord record = records[0]; 2811 2812 intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_NDEF_DISCOVERED); 2813 setTypeOrDataFromNdef(intent, record); 2814 2815 try { 2816 mContext.startActivity(intent); 2817 // If an activity is found then skip further dispatching 2818 return true; 2819 } catch (ActivityNotFoundException e) { 2820 if (DBG) Log.d(TAG, "No activities for NDEF handling of " + intent); 2821 } 2822 } 2823 } 2824 2825 // Try the technology specific dispatch 2826 intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TECHNOLOGY_DISCOVERED); 2827 intent.setData(buildTechListUri(tag)); 2828 try { 2829 mContext.startActivity(intent); 2830 return true; 2831 } catch (ActivityNotFoundException e) { 2832 if (DBG) Log.w(TAG, "No activities for technology handling of " + intent); 2833 } 2834 2835 // Try the generic intent 2836 intent = buildTagIntent(tag, msgs, NfcAdapter.ACTION_TAG_DISCOVERED); 2837 try { 2838 mContext.startActivity(intent); 2839 return true; 2840 } catch (ActivityNotFoundException e) { 2841 Log.e(TAG, "No tag fallback activity found for " + intent); 2842 return false; 2843 } 2844 } 2845 } 2846 2847 private NfcServiceHandler mHandler = new NfcServiceHandler(); 2848 2849 private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 2850 @Override 2851 protected Void doInBackground(Boolean... enable) { 2852 if (enable != null && enable.length > 0 && enable[0]) { 2853 synchronized (NfcService.this) { 2854 mScreenOn = true; 2855 maybeEnableDiscovery(); 2856 } 2857 } else { 2858 mWakeLock.acquire(); 2859 synchronized (NfcService.this) { 2860 mScreenOn = false; 2861 maybeDisableDiscovery(); 2862 } 2863 mWakeLock.release(); 2864 } 2865 return null; 2866 } 2867 } 2868 2869 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2870 @Override 2871 public void onReceive(Context context, Intent intent) { 2872 if (intent.getAction().equals( 2873 NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2874 if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 2875 2876 /* Restart polling loop for notification */ 2877 maybeEnableDiscovery(); 2878 2879 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 2880 // Perform discovery enable in thread to protect against ANR when the 2881 // NFC stack wedges. This is *not* the correct way to fix this issue - 2882 // configuration of the local NFC adapter should be very quick and should 2883 // be safe on the main thread, and the NFC stack should not wedge. 2884 new EnableDisableDiscoveryTask().execute(new Boolean(true)); 2885 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 2886 // Perform discovery disable in thread to protect against ANR when the 2887 // NFC stack wedges. This is *not* the correct way to fix this issue - 2888 // configuration of the local NFC adapter should be very quick and should 2889 // be safe on the main thread, and the NFC stack should not wedge. 2890 new EnableDisableDiscoveryTask().execute(new Boolean(false)); 2891 } 2892 } 2893 }; 2894} 2895