NfcService.java revision 70bbea61637e3f9eb7202efd243b9d2f9516a06a
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.DeviceHost.DeviceHostListener; 22import com.android.nfc.DeviceHost.NfcDepEndpoint; 23import com.android.nfc.DeviceHost.TagEndpoint; 24import com.android.nfc.nxp.NativeLlcpConnectionlessSocket; 25import com.android.nfc.nxp.NativeLlcpServiceSocket; 26import com.android.nfc.nxp.NativeLlcpSocket; 27import com.android.nfc.nxp.NativeNfcManager; 28import com.android.nfc.nxp.NativeNfcSecureElement; 29import com.android.nfc3.R; 30 31import android.app.Application; 32import android.app.KeyguardManager; 33import android.app.PendingIntent; 34import android.app.StatusBarManager; 35import android.content.BroadcastReceiver; 36import android.content.ComponentName; 37import android.content.Context; 38import android.content.Intent; 39import android.content.IntentFilter; 40import android.content.SharedPreferences; 41import android.content.pm.PackageManager; 42import android.media.AudioManager; 43import android.media.SoundPool; 44import android.net.Uri; 45import android.nfc.ErrorCodes; 46import android.nfc.FormatException; 47import android.nfc.ILlcpConnectionlessSocket; 48import android.nfc.ILlcpServiceSocket; 49import android.nfc.ILlcpSocket; 50import android.nfc.INdefPushCallback; 51import android.nfc.INfcAdapter; 52import android.nfc.INfcAdapterExtras; 53import android.nfc.INfcTag; 54import android.nfc.IP2pInitiator; 55import android.nfc.IP2pTarget; 56import android.nfc.LlcpPacket; 57import android.nfc.NdefMessage; 58import android.nfc.NdefRecord; 59import android.nfc.NfcAdapter; 60import android.nfc.Tag; 61import android.nfc.TechListParcel; 62import android.nfc.TransceiveResult; 63import android.nfc.tech.Ndef; 64import android.nfc.tech.TagTechnology; 65import android.os.AsyncTask; 66import android.os.Bundle; 67import android.os.Handler; 68import android.os.IBinder; 69import android.os.Message; 70import android.os.PowerManager; 71import android.os.RemoteException; 72import android.os.ServiceManager; 73import android.util.Log; 74 75import java.io.ByteArrayOutputStream; 76import java.io.DataInputStream; 77import java.io.FileInputStream; 78import java.io.FileNotFoundException; 79import java.io.FileOutputStream; 80import java.io.IOException; 81import java.util.ArrayList; 82import java.util.HashMap; 83import java.util.HashSet; 84import java.util.Iterator; 85import java.util.List; 86 87public class NfcService extends Application implements DeviceHostListener { 88 private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 89 90 static final boolean DBG = true; 91 static final String TAG = "NfcService"; 92 93 private static final String SE_RESET_SCRIPT_FILE_NAME = "/system/etc/se-reset-script"; 94 95 public static final String SERVICE_NAME = "nfc"; 96 97 private static final String NFC_PERM = android.Manifest.permission.NFC; 98 private static final String NFC_PERM_ERROR = "NFC permission required"; 99 private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 100 private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 101 private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; 102 private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required"; 103 104 /*package*/ static final String PREF = "NfcServicePrefs"; 105 106 private static final String PREF_NFC_ON = "nfc_on"; 107 private static final boolean NFC_ON_DEFAULT = true; 108 private static final String PREF_ZEROCLICK_ON = "zeroclick_on"; 109 private static final boolean ZEROCLICK_ON_DEFAULT = true; 110 111 private static final String PREF_FIRST_BOOT = "first_boot"; 112 113 static final int MSG_NDEF_TAG = 0; 114 static final int MSG_CARD_EMULATION = 1; 115 static final int MSG_LLCP_LINK_ACTIVATION = 2; 116 static final int MSG_LLCP_LINK_DEACTIVATED = 3; 117 static final int MSG_TARGET_DESELECTED = 4; 118 static final int MSG_MOCK_NDEF = 7; 119 static final int MSG_SE_FIELD_ACTIVATED = 8; 120 static final int MSG_SE_FIELD_DEACTIVATED = 9; 121 static final int MSG_SE_APDU_RECEIVED = 10; 122 static final int MSG_SE_EMV_CARD_REMOVAL = 11; 123 static final int MSG_SE_MIFARE_ACCESS = 12; 124 125 // Copied from com.android.nfc_extras to avoid library dependency 126 // Must keep in sync with com.android.nfc_extras 127 static final int ROUTE_OFF = 1; 128 static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 129 130 public static final String ACTION_RF_FIELD_ON_DETECTED = 131 "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 132 public static final String ACTION_RF_FIELD_OFF_DETECTED = 133 "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 134 public static final String ACTION_AID_SELECTED = 135 "com.android.nfc_extras.action.AID_SELECTED"; 136 public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 137 138 public static final String ACTION_APDU_RECEIVED = 139 "com.android.nfc_extras.action.APDU_RECEIVED"; 140 public static final String EXTRA_APDU_BYTES = 141 "com.android.nfc_extras.extra.APDU_BYTES"; 142 143 public static final String ACTION_EMV_CARD_REMOVAL = 144 "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 145 146 public static final String ACTION_MIFARE_ACCESS_DETECTED = 147 "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 148 public static final String EXTRA_MIFARE_BLOCK = 149 "com.android.nfc_extras.extra.MIFARE_BLOCK"; 150 151 // TODO: none of these appear to be synchronized but are 152 // read/written from different threads (notably Binder threads)... 153 private int mGeneratedSocketHandle = 0; 154 private volatile boolean mIsNfcEnabled = false; 155 private boolean mIsDiscoveryOn = false; 156 private boolean mZeroClickOn = false; 157 158 // NFC Execution Environment 159 // fields below are protected by this 160 private NativeNfcSecureElement mSecureElement; 161 private OpenSecureElement mOpenEe; // null when EE closed 162 private int mEeRoutingState; // contactless interface routing 163 164 // fields below are used in multiple threads and protected by synchronized(this) 165 private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 166 private final HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>(); 167 private boolean mScreenUnlocked; 168 private HashSet<String> mSePackages = new HashSet<String>(); 169 170 // fields below are final after onCreate() 171 Context mContext; 172 private NativeNfcManager mDeviceHost; 173 private SharedPreferences mPrefs; 174 private SharedPreferences.Editor mPrefsEditor; 175 private PowerManager.WakeLock mWakeLock; 176 NdefP2pManager mP2pManager; 177 int mStartSound; 178 int mEndSound; 179 int mErrorSound; 180 SoundPool mSoundPool; // playback synchronized on this 181 182 private NfcDispatcher mNfcDispatcher; 183 private KeyguardManager mKeyguard; 184 185 private static NfcService sService; 186 187 public static void enforceAdminPerm(Context context) { 188 int admin = context.checkCallingOrSelfPermission(ADMIN_PERM); 189 int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM); 190 if (admin != PackageManager.PERMISSION_GRANTED 191 && nfcee != PackageManager.PERMISSION_GRANTED) { 192 throw new SecurityException(ADMIN_PERM_ERROR); 193 } 194 } 195 196 public static void enforceNfceeAdminPerm(Context context) { 197 context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR); 198 } 199 200 public static NfcService getInstance() { 201 return sService; 202 } 203 204 @Override 205 public void onRemoteEndpointDiscovered(TagEndpoint tag) { 206 sendMessage(NfcService.MSG_NDEF_TAG, tag); 207 } 208 209 /** 210 * Notifies transaction 211 */ 212 @Override 213 public void onCardEmulationDeselected() { 214 sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 215 } 216 217 /** 218 * Notifies transaction 219 */ 220 @Override 221 public void onCardEmulationAidSelected(byte[] aid) { 222 sendMessage(NfcService.MSG_CARD_EMULATION, aid); 223 } 224 225 /** 226 * Notifies P2P Device detected, to activate LLCP link 227 */ 228 @Override 229 public void onLlcpLinkActivated(NfcDepEndpoint device) { 230 sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 231 } 232 233 /** 234 * Notifies P2P Device detected, to activate LLCP link 235 */ 236 @Override 237 public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 238 sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 239 } 240 241 @Override 242 public void onRemoteFieldActivated() { 243 sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 244 } 245 246 @Override 247 public void onRemoteFieldDeactivated() { 248 sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 249 } 250 251 @Override 252 public void onSeApduReceived(byte[] apdu) { 253 sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 254 } 255 256 @Override 257 public void onSeEmvCardRemoval() { 258 sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 259 } 260 261 @Override 262 public void onSeMifareAccess(byte[] block) { 263 sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 264 } 265 266 @Override 267 public void onCreate() { 268 super.onCreate(); 269 270 Log.i(TAG, "Starting NFC service"); 271 272 sService = this; 273 274 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 275 mStartSound = mSoundPool.load(this, R.raw.start, 1); 276 mEndSound = mSoundPool.load(this, R.raw.end, 1); 277 mErrorSound = mSoundPool.load(this, R.raw.error, 1); 278 279 mContext = this; 280 mDeviceHost = new NativeNfcManager(this, this); 281 mDeviceHost.initializeNativeStructure(); 282 283 mP2pManager = new NdefP2pManager(this, mNfcAdapter); 284 mNfcDispatcher = new NfcDispatcher(this, mP2pManager); 285 286 mSecureElement = new NativeNfcSecureElement(); 287 mEeRoutingState = ROUTE_OFF; 288 289 mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 290 mPrefsEditor = mPrefs.edit(); 291 292 mIsNfcEnabled = false; // load from preferences later 293 294 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 295 296 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 297 mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 298 mScreenUnlocked = !mKeyguard.isKeyguardLocked() && !mKeyguard.isKeyguardSecure(); 299 300 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 301 302 IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 303 filter.addAction(Intent.ACTION_SCREEN_OFF); 304 filter.addAction(Intent.ACTION_SCREEN_ON); 305 filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 306 filter.addAction(Intent.ACTION_USER_PRESENT); 307 registerReceiver(mReceiver, filter); 308 309 filter = new IntentFilter(); 310 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 311 filter.addDataScheme("package"); 312 313 registerReceiver(mReceiver, filter); 314 315 Thread t = new Thread() { 316 @Override 317 public void run() { 318 boolean nfc_on = mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT); 319 if (nfc_on) { 320 _enable(false, true); 321 } 322 resetSeOnFirstBoot(); 323 } 324 }; 325 t.start(); 326 } 327 328 public void playSound(int sound) { 329 synchronized (this) { 330 mSoundPool.play(sound, 1.0f, 1.0f, 0, 0, 1.0f); 331 } 332 } 333 334 @Override 335 public void onTerminate() { 336 super.onTerminate(); 337 // NFC application is persistent, it should not be destroyed by framework 338 Log.wtf(TAG, "NFC service is under attack!"); 339 } 340 341 private final INfcAdapter.Stub mNfcAdapter = new INfcAdapter.Stub() { 342 /** Protected by "this" */ 343 NdefMessage mLocalMessage = null; 344 345 @Override 346 public boolean enable() throws RemoteException { 347 NfcService.enforceAdminPerm(mContext); 348 349 boolean isSuccess = false; 350 boolean previouslyEnabled = isEnabled(); 351 if (!previouslyEnabled) { 352 reset(); 353 isSuccess = _enable(previouslyEnabled, true); 354 } 355 return isSuccess; 356 } 357 358 @Override 359 public boolean disable() throws RemoteException { 360 boolean isSuccess = false; 361 NfcService.enforceAdminPerm(mContext); 362 boolean previouslyEnabled = isEnabled(); 363 if (DBG) Log.d(TAG, "Disabling NFC. previous=" + previouslyEnabled); 364 365 if (previouslyEnabled) { 366 isSuccess = _disable(previouslyEnabled, true); 367 } 368 return isSuccess; 369 } 370 371 @Override 372 public boolean zeroClickEnabled() throws RemoteException { 373 return mZeroClickOn; 374 } 375 376 @Override 377 public boolean enableZeroClick() throws RemoteException { 378 NfcService.enforceAdminPerm(mContext); 379 synchronized(NfcService.this) { 380 if (!mZeroClickOn) { 381 Log.e(TAG, "ENABLING 0-CLICK"); 382 mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, true); 383 mPrefsEditor.apply(); 384 mP2pManager.enableNdefServer(); 385 mZeroClickOn = true; 386 } 387 } 388 return true; 389 } 390 391 @Override 392 public boolean disableZeroClick() throws RemoteException { 393 NfcService.enforceAdminPerm(mContext); 394 synchronized(NfcService.this) { 395 if (mZeroClickOn) { 396 Log.e(TAG, "DISABLING 0-CLICK"); 397 mPrefsEditor.putBoolean(PREF_ZEROCLICK_ON, false); 398 mPrefsEditor.apply(); 399 mP2pManager.disableNdefServer(); 400 mZeroClickOn = false; 401 } 402 } 403 return true; 404 } 405 406 407 @Override 408 public void enableForegroundDispatch(ComponentName activity, PendingIntent intent, 409 IntentFilter[] filters, TechListParcel techListsParcel) { 410 // Permission check 411 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 412 413 // Argument validation 414 if (activity == null || intent == null) { 415 throw new IllegalArgumentException(); 416 } 417 418 // Validate the IntentFilters 419 if (filters != null) { 420 if (filters.length == 0) { 421 filters = null; 422 } else { 423 for (IntentFilter filter : filters) { 424 if (filter == null) { 425 throw new IllegalArgumentException("null IntentFilter"); 426 } 427 } 428 } 429 } 430 431 // Validate the tech lists 432 String[][] techLists = null; 433 if (techListsParcel != null) { 434 techLists = techListsParcel.getTechLists(); 435 } 436 437 mNfcDispatcher.enableForegroundDispatch(intent, filters, techLists); 438 } 439 440 @Override 441 public void disableForegroundDispatch(ComponentName activity) { 442 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 443 444 mNfcDispatcher.disableForegroundDispatch(); 445 } 446 447 @Override 448 public void enableForegroundNdefPush(ComponentName activity, NdefMessage msg) { 449 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 450 if (activity == null || msg == null) { 451 throw new IllegalArgumentException(); 452 } 453 if (mP2pManager.setForegroundMessage(msg)) { 454 Log.e(TAG, "Replacing active NDEF push message"); 455 } 456 } 457 458 @Override 459 public void enableForegroundNdefPushWithCallback(ComponentName activity, 460 INdefPushCallback callback) { 461 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 462 if (activity == null || callback == null) { 463 throw new IllegalArgumentException(); 464 } 465 if (mP2pManager.setForegroundCallback(callback)) { 466 Log.e(TAG, "Replacing active NDEF push message"); 467 } 468 } 469 470 @Override 471 public void disableForegroundNdefPush(ComponentName activity) { 472 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 473 boolean hadMsg = mP2pManager.setForegroundMessage(null); 474 boolean hadCallback = mP2pManager.setForegroundCallback(null); 475 if (!hadMsg || !hadCallback) { 476 Log.e(TAG, "No active foreground NDEF push message"); 477 } 478 } 479 480 @Override 481 public int createLlcpConnectionlessSocket(int sap) throws RemoteException { 482 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 483 484 // Check if NFC is enabled 485 if (!mIsNfcEnabled) { 486 return ErrorCodes.ERROR_NOT_INITIALIZED; 487 } 488 489 /* Check SAP is not already used */ 490 491 /* Store the socket handle */ 492 int sockeHandle = mGeneratedSocketHandle; 493 NativeLlcpConnectionlessSocket socket; 494 495 socket = mDeviceHost.doCreateLlcpConnectionlessSocket(sap); 496 if (socket != null) { 497 synchronized(NfcService.this) { 498 /* update socket handle generation */ 499 mGeneratedSocketHandle++; 500 501 /* Add the socket into the socket map */ 502 mSocketMap.put(mGeneratedSocketHandle, socket); 503 return mGeneratedSocketHandle; 504 } 505 } else { 506 /* Get Error Status */ 507 int errorStatus = mDeviceHost.doGetLastError(); 508 509 switch (errorStatus) { 510 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 511 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 512 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 513 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 514 default: 515 return ErrorCodes.ERROR_SOCKET_CREATION; 516 } 517 } 518 } 519 520 @Override 521 public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength) 522 throws RemoteException { 523 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 524 525 // Check if NFC is enabled 526 if (!mIsNfcEnabled) { 527 return ErrorCodes.ERROR_NOT_INITIALIZED; 528 } 529 530 NativeLlcpServiceSocket socket; 531 532 socket = mDeviceHost.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 533 if (socket != null) { 534 synchronized(NfcService.this) { 535 /* update socket handle generation */ 536 mGeneratedSocketHandle++; 537 538 /* Add the socket into the socket map */ 539 mSocketMap.put(mGeneratedSocketHandle, socket); 540 return mGeneratedSocketHandle; 541 } 542 } else { 543 /* Get Error Status */ 544 int errorStatus = mDeviceHost.doGetLastError(); 545 546 switch (errorStatus) { 547 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 548 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 549 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 550 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 551 default: 552 return ErrorCodes.ERROR_SOCKET_CREATION; 553 } 554 } 555 } 556 557 @Override 558 public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 559 throws RemoteException { 560 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 561 562 // Check if NFC is enabled 563 if (!mIsNfcEnabled) { 564 return ErrorCodes.ERROR_NOT_INITIALIZED; 565 } 566 567 if (DBG) Log.d(TAG, "creating llcp socket"); 568 NativeLlcpSocket socket; 569 570 socket = mDeviceHost.doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 571 572 if (socket != null) { 573 synchronized(NfcService.this) { 574 /* update socket handle generation */ 575 mGeneratedSocketHandle++; 576 577 /* Add the socket into the socket map */ 578 mSocketMap.put(mGeneratedSocketHandle, socket); 579 return mGeneratedSocketHandle; 580 } 581 } else { 582 /* Get Error Status */ 583 int errorStatus = mDeviceHost.doGetLastError(); 584 585 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(errorStatus)); 586 587 switch (errorStatus) { 588 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 589 return ErrorCodes.ERROR_BUFFER_TO_SMALL; 590 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 591 return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; 592 default: 593 return ErrorCodes.ERROR_SOCKET_CREATION; 594 } 595 } 596 } 597 598 @Override 599 public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException { 600 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 601 return mLlcpConnectionlessSocketService; 602 } 603 604 @Override 605 public ILlcpSocket getLlcpInterface() throws RemoteException { 606 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 607 return mLlcpSocket; 608 } 609 610 @Override 611 public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException { 612 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 613 return mLlcpServerSocketService; 614 } 615 616 @Override 617 public INfcTag getNfcTagInterface() throws RemoteException { 618 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 619 return mNfcTagService; 620 } 621 622 @Override 623 public IP2pInitiator getP2pInitiatorInterface() throws RemoteException { 624 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 625 return mP2pInitiatorService; 626 } 627 628 @Override 629 public IP2pTarget getP2pTargetInterface() throws RemoteException { 630 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 631 return mP2pTargetService; 632 } 633 634 @Override 635 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 636 NfcService.enforceNfceeAdminPerm(mContext); 637 return mExtrasService; 638 } 639 640 @Override 641 public boolean isEnabled() throws RemoteException { 642 return mIsNfcEnabled; 643 } 644 }; 645 646 private final ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() { 647 648 private NativeLlcpSocket findSocket(int nativeHandle) { 649 Object socket = NfcService.this.findSocket(nativeHandle); 650 if (!(socket instanceof NativeLlcpSocket)) { 651 return null; 652 } 653 return (NativeLlcpSocket) socket; 654 } 655 656 @Override 657 public int close(int nativeHandle) throws RemoteException { 658 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 659 660 NativeLlcpSocket socket = null; 661 662 // Check if NFC is enabled 663 if (!mIsNfcEnabled) { 664 return ErrorCodes.ERROR_NOT_INITIALIZED; 665 } 666 667 /* find the socket in the hmap */ 668 socket = findSocket(nativeHandle); 669 if (socket != null) { 670 socket.doClose(); 671 /* Remove the socket closed from the hmap */ 672 removeSocket(nativeHandle); 673 return ErrorCodes.SUCCESS; 674 } else { 675 return ErrorCodes.ERROR_IO; 676 } 677 } 678 679 @Override 680 public int connect(int nativeHandle, int sap) throws RemoteException { 681 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 682 683 NativeLlcpSocket socket = null; 684 boolean isSuccess = false; 685 686 // Check if NFC is enabled 687 if (!mIsNfcEnabled) { 688 return ErrorCodes.ERROR_NOT_INITIALIZED; 689 } 690 691 /* find the socket in the hmap */ 692 socket = findSocket(nativeHandle); 693 if (socket != null) { 694 isSuccess = socket.doConnect(sap); 695 if (isSuccess) { 696 return ErrorCodes.SUCCESS; 697 } else { 698 return ErrorCodes.ERROR_IO; 699 } 700 } else { 701 return ErrorCodes.ERROR_IO; 702 } 703 704 } 705 706 @Override 707 public int connectByName(int nativeHandle, String sn) throws RemoteException { 708 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 709 710 NativeLlcpSocket socket = null; 711 boolean isSuccess = false; 712 713 // Check if NFC is enabled 714 if (!mIsNfcEnabled) { 715 return ErrorCodes.ERROR_NOT_INITIALIZED; 716 } 717 718 /* find the socket in the hmap */ 719 socket = findSocket(nativeHandle); 720 if (socket != null) { 721 isSuccess = socket.doConnectBy(sn); 722 if (isSuccess) { 723 return ErrorCodes.SUCCESS; 724 } else { 725 return ErrorCodes.ERROR_IO; 726 } 727 } else { 728 return ErrorCodes.ERROR_IO; 729 } 730 731 } 732 733 @Override 734 public int getLocalSap(int nativeHandle) throws RemoteException { 735 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 736 737 NativeLlcpSocket socket = null; 738 739 // Check if NFC is enabled 740 if (!mIsNfcEnabled) { 741 return ErrorCodes.ERROR_NOT_INITIALIZED; 742 } 743 744 /* find the socket in the hmap */ 745 socket = findSocket(nativeHandle); 746 if (socket != null) { 747 return socket.getSap(); 748 } else { 749 return 0; 750 } 751 } 752 753 @Override 754 public int getLocalSocketMiu(int nativeHandle) throws RemoteException { 755 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 756 757 NativeLlcpSocket socket = null; 758 759 // Check if NFC is enabled 760 if (!mIsNfcEnabled) { 761 return ErrorCodes.ERROR_NOT_INITIALIZED; 762 } 763 764 /* find the socket in the hmap */ 765 socket = findSocket(nativeHandle); 766 if (socket != null) { 767 return socket.getMiu(); 768 } else { 769 return 0; 770 } 771 } 772 773 @Override 774 public int getLocalSocketRw(int nativeHandle) throws RemoteException { 775 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 776 777 NativeLlcpSocket socket = null; 778 779 // Check if NFC is enabled 780 if (!mIsNfcEnabled) { 781 return ErrorCodes.ERROR_NOT_INITIALIZED; 782 } 783 784 /* find the socket in the hmap */ 785 socket = findSocket(nativeHandle); 786 if (socket != null) { 787 return socket.getRw(); 788 } else { 789 return 0; 790 } 791 } 792 793 @Override 794 public int getRemoteSocketMiu(int nativeHandle) throws RemoteException { 795 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 796 797 NativeLlcpSocket socket = null; 798 799 // Check if NFC is enabled 800 if (!mIsNfcEnabled) { 801 return ErrorCodes.ERROR_NOT_INITIALIZED; 802 } 803 804 /* find the socket in the hmap */ 805 socket = findSocket(nativeHandle); 806 if (socket != null) { 807 if (socket.doGetRemoteSocketMiu() != 0) { 808 return socket.doGetRemoteSocketMiu(); 809 } else { 810 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 811 } 812 } else { 813 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 814 } 815 } 816 817 @Override 818 public int getRemoteSocketRw(int nativeHandle) throws RemoteException { 819 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 820 821 NativeLlcpSocket socket = null; 822 823 // Check if NFC is enabled 824 if (!mIsNfcEnabled) { 825 return ErrorCodes.ERROR_NOT_INITIALIZED; 826 } 827 828 /* find the socket in the hmap */ 829 socket = findSocket(nativeHandle); 830 if (socket != null) { 831 if (socket.doGetRemoteSocketRw() != 0) { 832 return socket.doGetRemoteSocketRw(); 833 } else { 834 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 835 } 836 } else { 837 return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; 838 } 839 } 840 841 @Override 842 public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException { 843 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 844 845 NativeLlcpSocket socket = null; 846 847 // Check if NFC is enabled 848 if (!mIsNfcEnabled) { 849 return ErrorCodes.ERROR_NOT_INITIALIZED; 850 } 851 852 /* find the socket in the hmap */ 853 socket = findSocket(nativeHandle); 854 if (socket != null) { 855 return socket.doReceive(receiveBuffer); 856 } else { 857 return 0; 858 } 859 } 860 861 @Override 862 public int send(int nativeHandle, byte[] data) throws RemoteException { 863 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 864 865 NativeLlcpSocket socket = null; 866 boolean isSuccess = false; 867 868 // Check if NFC is enabled 869 if (!mIsNfcEnabled) { 870 return ErrorCodes.ERROR_NOT_INITIALIZED; 871 } 872 873 /* find the socket in the hmap */ 874 socket = findSocket(nativeHandle); 875 if (socket != null) { 876 isSuccess = socket.doSend(data); 877 if (isSuccess) { 878 return ErrorCodes.SUCCESS; 879 } else { 880 return ErrorCodes.ERROR_IO; 881 } 882 } else { 883 return ErrorCodes.ERROR_IO; 884 } 885 } 886 }; 887 888 private final ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() { 889 890 private NativeLlcpServiceSocket findSocket(int nativeHandle) { 891 Object socket = NfcService.this.findSocket(nativeHandle); 892 if (!(socket instanceof NativeLlcpServiceSocket)) { 893 return null; 894 } 895 return (NativeLlcpServiceSocket) socket; 896 } 897 898 @Override 899 public int accept(int nativeHandle) throws RemoteException { 900 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 901 902 NativeLlcpServiceSocket socket = null; 903 NativeLlcpSocket clientSocket = null; 904 905 // Check if NFC is enabled 906 if (!mIsNfcEnabled) { 907 return ErrorCodes.ERROR_NOT_INITIALIZED; 908 } 909 910 /* find the socket in the hmap */ 911 socket = findSocket(nativeHandle); 912 if (socket != null) { 913 clientSocket = socket.doAccept(socket.getMiu(), 914 socket.getRw(), socket.getLinearBufferLength()); 915 if (clientSocket != null) { 916 /* Add the socket into the socket map */ 917 synchronized(this) { 918 mGeneratedSocketHandle++; 919 mSocketMap.put(mGeneratedSocketHandle, clientSocket); 920 return mGeneratedSocketHandle; 921 } 922 } else { 923 return ErrorCodes.ERROR_IO; 924 } 925 } else { 926 return ErrorCodes.ERROR_IO; 927 } 928 } 929 930 @Override 931 public void close(int nativeHandle) throws RemoteException { 932 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 933 934 NativeLlcpServiceSocket socket = null; 935 936 // Check if NFC is enabled 937 if (!mIsNfcEnabled) { 938 return; 939 } 940 941 /* find the socket in the hmap */ 942 socket = findSocket(nativeHandle); 943 if (socket != null) { 944 socket.doClose(); 945 synchronized (this) { 946 /* Remove the socket closed from the hmap */ 947 removeSocket(nativeHandle); 948 } 949 } 950 } 951 }; 952 953 private final ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() { 954 955 private NativeLlcpConnectionlessSocket findSocket(int nativeHandle) { 956 Object socket = NfcService.this.findSocket(nativeHandle); 957 if (!(socket instanceof NativeLlcpConnectionlessSocket)) { 958 return null; 959 } 960 return (NativeLlcpConnectionlessSocket) socket; 961 } 962 963 @Override 964 public void close(int nativeHandle) throws RemoteException { 965 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 966 967 NativeLlcpConnectionlessSocket socket = null; 968 969 // Check if NFC is enabled 970 if (!mIsNfcEnabled) { 971 return; 972 } 973 974 /* find the socket in the hmap */ 975 socket = findSocket(nativeHandle); 976 if (socket != null) { 977 socket.doClose(); 978 /* Remove the socket closed from the hmap */ 979 removeSocket(nativeHandle); 980 } 981 } 982 983 @Override 984 public int getSap(int nativeHandle) throws RemoteException { 985 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 986 987 NativeLlcpConnectionlessSocket socket = null; 988 989 // Check if NFC is enabled 990 if (!mIsNfcEnabled) { 991 return ErrorCodes.ERROR_NOT_INITIALIZED; 992 } 993 994 /* find the socket in the hmap */ 995 socket = findSocket(nativeHandle); 996 if (socket != null) { 997 return socket.getSap(); 998 } else { 999 return 0; 1000 } 1001 } 1002 1003 @Override 1004 public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException { 1005 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1006 1007 NativeLlcpConnectionlessSocket socket = null; 1008 LlcpPacket packet; 1009 1010 // Check if NFC is enabled 1011 if (!mIsNfcEnabled) { 1012 return null; 1013 } 1014 1015 /* find the socket in the hmap */ 1016 socket = findSocket(nativeHandle); 1017 if (socket != null) { 1018 packet = socket.doReceiveFrom(socket.getLinkMiu()); 1019 if (packet != null) { 1020 return packet; 1021 } 1022 return null; 1023 } else { 1024 return null; 1025 } 1026 } 1027 1028 @Override 1029 public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException { 1030 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1031 1032 NativeLlcpConnectionlessSocket socket = null; 1033 boolean isSuccess = false; 1034 1035 // Check if NFC is enabled 1036 if (!mIsNfcEnabled) { 1037 return ErrorCodes.ERROR_NOT_INITIALIZED; 1038 } 1039 1040 /* find the socket in the hmap */ 1041 socket = findSocket(nativeHandle); 1042 if (socket != null) { 1043 isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer()); 1044 if (isSuccess) { 1045 return ErrorCodes.SUCCESS; 1046 } else { 1047 return ErrorCodes.ERROR_IO; 1048 } 1049 } else { 1050 return ErrorCodes.ERROR_IO; 1051 } 1052 } 1053 }; 1054 1055 private final INfcTag mNfcTagService = new INfcTag.Stub() { 1056 1057 @Override 1058 public int close(int nativeHandle) throws RemoteException { 1059 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1060 1061 TagEndpoint tag = null; 1062 1063 // Check if NFC is enabled 1064 if (!mIsNfcEnabled) { 1065 return ErrorCodes.ERROR_NOT_INITIALIZED; 1066 } 1067 1068 /* find the tag in the hmap */ 1069 tag = (TagEndpoint) findObject(nativeHandle); 1070 if (tag != null) { 1071 /* Remove the device from the hmap */ 1072 unregisterObject(nativeHandle); 1073 tag.disconnect(); 1074 return ErrorCodes.SUCCESS; 1075 } 1076 /* Restart polling loop for notification */ 1077 applyRouting(); 1078 return ErrorCodes.ERROR_DISCONNECT; 1079 } 1080 1081 @Override 1082 public int connect(int nativeHandle, int technology) throws RemoteException { 1083 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1084 1085 TagEndpoint tag = null; 1086 1087 // Check if NFC is enabled 1088 if (!mIsNfcEnabled) { 1089 return ErrorCodes.ERROR_NOT_INITIALIZED; 1090 } 1091 1092 /* find the tag in the hmap */ 1093 tag = (TagEndpoint) findObject(nativeHandle); 1094 if (tag == null) { 1095 return ErrorCodes.ERROR_DISCONNECT; 1096 } 1097 1098 if (technology == TagTechnology.NFC_B) { 1099 return ErrorCodes.ERROR_NOT_SUPPORTED; 1100 } 1101 1102 // Note that on most tags, all technologies are behind a single 1103 // handle. This means that the connect at the lower levels 1104 // will do nothing, as the tag is already connected to that handle. 1105 if (tag.connect(technology)) { 1106 return ErrorCodes.SUCCESS; 1107 } else { 1108 return ErrorCodes.ERROR_DISCONNECT; 1109 } 1110 } 1111 1112 @Override 1113 public int reconnect(int nativeHandle) throws RemoteException { 1114 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1115 1116 TagEndpoint tag = null; 1117 1118 // Check if NFC is enabled 1119 if (!mIsNfcEnabled) { 1120 return ErrorCodes.ERROR_NOT_INITIALIZED; 1121 } 1122 1123 /* find the tag in the hmap */ 1124 tag = (TagEndpoint) findObject(nativeHandle); 1125 if (tag != null) { 1126 if (tag.reconnect()) { 1127 return ErrorCodes.SUCCESS; 1128 } else { 1129 return ErrorCodes.ERROR_DISCONNECT; 1130 } 1131 } 1132 return ErrorCodes.ERROR_DISCONNECT; 1133 } 1134 1135 @Override 1136 public int[] getTechList(int nativeHandle) throws RemoteException { 1137 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1138 1139 // Check if NFC is enabled 1140 if (!mIsNfcEnabled) { 1141 return null; 1142 } 1143 1144 /* find the tag in the hmap */ 1145 TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 1146 if (tag != null) { 1147 return tag.getTechList(); 1148 } 1149 return null; 1150 } 1151 1152 @Override 1153 public byte[] getUid(int nativeHandle) throws RemoteException { 1154 TagEndpoint tag = null; 1155 byte[] uid; 1156 1157 // Check if NFC is enabled 1158 if (!mIsNfcEnabled) { 1159 return null; 1160 } 1161 1162 /* find the tag in the hmap */ 1163 tag = (TagEndpoint) findObject(nativeHandle); 1164 if (tag != null) { 1165 uid = tag.getUid(); 1166 return uid; 1167 } 1168 return null; 1169 } 1170 1171 @Override 1172 public boolean isPresent(int nativeHandle) throws RemoteException { 1173 TagEndpoint tag = null; 1174 1175 // Check if NFC is enabled 1176 if (!mIsNfcEnabled) { 1177 return false; 1178 } 1179 1180 /* find the tag in the hmap */ 1181 tag = (TagEndpoint) findObject(nativeHandle); 1182 if (tag == null) { 1183 return false; 1184 } 1185 1186 return tag.isPresent(); 1187 } 1188 1189 @Override 1190 public boolean isNdef(int nativeHandle) throws RemoteException { 1191 TagEndpoint tag = null; 1192 1193 // Check if NFC is enabled 1194 if (!mIsNfcEnabled) { 1195 return false; 1196 } 1197 1198 /* find the tag in the hmap */ 1199 tag = (TagEndpoint) findObject(nativeHandle); 1200 int[] ndefInfo = new int[2]; 1201 if (tag == null) { 1202 return false; 1203 } 1204 return tag.checkNdef(ndefInfo); 1205 } 1206 1207 @Override 1208 public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 1209 throws RemoteException { 1210 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1211 1212 TagEndpoint tag = null; 1213 byte[] response; 1214 1215 // Check if NFC is enabled 1216 if (!mIsNfcEnabled) { 1217 return null; 1218 } 1219 1220 /* find the tag in the hmap */ 1221 tag = (TagEndpoint) findObject(nativeHandle); 1222 if (tag != null) { 1223 int[] targetLost = new int[1]; 1224 response = tag.transceive(data, raw, targetLost); 1225 TransceiveResult transResult = new TransceiveResult( 1226 (response != null) ? true : false, 1227 (targetLost[0] == 1) ? true : false, 1228 response); 1229 return transResult; 1230 } 1231 return null; 1232 } 1233 1234 @Override 1235 public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1236 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1237 1238 TagEndpoint tag; 1239 1240 // Check if NFC is enabled 1241 if (!mIsNfcEnabled) { 1242 return null; 1243 } 1244 1245 /* find the tag in the hmap */ 1246 tag = (TagEndpoint) findObject(nativeHandle); 1247 if (tag != null) { 1248 byte[] buf = tag.readNdef(); 1249 if (buf == null) { 1250 return null; 1251 } 1252 1253 /* Create an NdefMessage */ 1254 try { 1255 return new NdefMessage(buf); 1256 } catch (FormatException e) { 1257 return null; 1258 } 1259 } 1260 return null; 1261 } 1262 1263 @Override 1264 public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1265 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1266 1267 TagEndpoint tag; 1268 1269 // Check if NFC is enabled 1270 if (!mIsNfcEnabled) { 1271 return ErrorCodes.ERROR_NOT_INITIALIZED; 1272 } 1273 1274 /* find the tag in the hmap */ 1275 tag = (TagEndpoint) findObject(nativeHandle); 1276 if (tag == null) { 1277 return ErrorCodes.ERROR_IO; 1278 } 1279 1280 if (tag.writeNdef(msg.toByteArray())) { 1281 return ErrorCodes.SUCCESS; 1282 } else { 1283 return ErrorCodes.ERROR_IO; 1284 } 1285 1286 } 1287 1288 @Override 1289 public int getLastError(int nativeHandle) throws RemoteException { 1290 return(mDeviceHost.doGetLastError()); 1291 } 1292 1293 @Override 1294 public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 1295 throw new UnsupportedOperationException(); 1296 } 1297 1298 @Override 1299 public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 1300 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1301 1302 TagEndpoint tag; 1303 1304 // Check if NFC is enabled 1305 if (!mIsNfcEnabled) { 1306 return ErrorCodes.ERROR_NOT_INITIALIZED; 1307 } 1308 1309 /* find the tag in the hmap */ 1310 tag = (TagEndpoint) findObject(nativeHandle); 1311 if (tag == null) { 1312 return ErrorCodes.ERROR_IO; 1313 } 1314 1315 if (tag.makeReadOnly()) { 1316 return ErrorCodes.SUCCESS; 1317 } else { 1318 return ErrorCodes.ERROR_IO; 1319 } 1320 } 1321 1322 @Override 1323 public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 1324 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1325 1326 TagEndpoint tag; 1327 1328 // Check if NFC is enabled 1329 if (!mIsNfcEnabled) { 1330 return ErrorCodes.ERROR_NOT_INITIALIZED; 1331 } 1332 1333 /* find the tag in the hmap */ 1334 tag = (TagEndpoint) findObject(nativeHandle); 1335 if (tag == null) { 1336 return ErrorCodes.ERROR_IO; 1337 } 1338 1339 if (tag.formatNdef(key)) { 1340 return ErrorCodes.SUCCESS; 1341 } else { 1342 return ErrorCodes.ERROR_IO; 1343 } 1344 } 1345 1346 @Override 1347 public Tag rediscover(int nativeHandle) throws RemoteException { 1348 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1349 1350 TagEndpoint tag = null; 1351 1352 // Check if NFC is enabled 1353 if (!mIsNfcEnabled) { 1354 return null; 1355 } 1356 1357 /* find the tag in the hmap */ 1358 tag = (TagEndpoint) findObject(nativeHandle); 1359 if (tag != null) { 1360 // For now the prime usecase for rediscover() is to be able 1361 // to access the NDEF technology after formatting without 1362 // having to remove the tag from the field, or similar 1363 // to have access to NdefFormatable in case low-level commands 1364 // were used to remove NDEF. So instead of doing a full stack 1365 // rediscover (which is poorly supported at the moment anyway), 1366 // we simply remove these two technologies and detect them 1367 // again. 1368 tag.removeTechnology(TagTechnology.NDEF); 1369 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1370 NdefMessage[] msgs = tag.findAndReadNdef(); 1371 // Build a new Tag object to return 1372 Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 1373 tag.getTechExtras(), tag.getHandle(), mNfcTagService); 1374 return newTag; 1375 } 1376 return null; 1377 } 1378 1379 @Override 1380 public int setTimeout(int tech, int timeout) throws RemoteException { 1381 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1382 boolean success = mDeviceHost.setTimeout(tech, timeout); 1383 if (success) { 1384 return ErrorCodes.SUCCESS; 1385 } else { 1386 return ErrorCodes.ERROR_INVALID_PARAM; 1387 } 1388 } 1389 1390 @Override 1391 public int getTimeout(int tech) throws RemoteException { 1392 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1393 1394 return mDeviceHost.getTimeout(tech); 1395 } 1396 1397 @Override 1398 public void resetTimeouts() throws RemoteException { 1399 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1400 1401 mDeviceHost.resetTimeouts(); 1402 } 1403 }; 1404 1405 private final IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() { 1406 1407 @Override 1408 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1409 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1410 1411 NfcDepEndpoint device; 1412 1413 // Check if NFC is enabled 1414 if (!mIsNfcEnabled) { 1415 return null; 1416 } 1417 1418 /* find the device in the hmap */ 1419 device = (NfcDepEndpoint) findObject(nativeHandle); 1420 if (device != null) { 1421 byte[] buff = device.getGeneralBytes(); 1422 if (buff == null) 1423 return null; 1424 return buff; 1425 } 1426 return null; 1427 } 1428 1429 @Override 1430 public int getMode(int nativeHandle) throws RemoteException { 1431 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1432 1433 NfcDepEndpoint device; 1434 1435 // Check if NFC is enabled 1436 if (!mIsNfcEnabled) { 1437 return ErrorCodes.ERROR_NOT_INITIALIZED; 1438 } 1439 1440 /* find the device in the hmap */ 1441 device = (NfcDepEndpoint) findObject(nativeHandle); 1442 if (device != null) { 1443 return device.getMode(); 1444 } 1445 return ErrorCodes.ERROR_INVALID_PARAM; 1446 } 1447 1448 @Override 1449 public byte[] receive(int nativeHandle) throws RemoteException { 1450 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1451 1452 NfcDepEndpoint device; 1453 1454 // Check if NFC is enabled 1455 if (!mIsNfcEnabled) { 1456 return null; 1457 } 1458 1459 /* find the device in the hmap */ 1460 device = (NfcDepEndpoint) findObject(nativeHandle); 1461 if (device != null) { 1462 byte[] buff = device.receive(); 1463 if (buff == null) { 1464 return null; 1465 } 1466 return buff; 1467 } 1468 /* Restart polling loop for notification */ 1469 applyRouting(); 1470 return null; 1471 } 1472 1473 @Override 1474 public boolean send(int nativeHandle, byte[] data) throws RemoteException { 1475 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1476 1477 NfcDepEndpoint device; 1478 boolean isSuccess = false; 1479 1480 // Check if NFC is enabled 1481 if (!mIsNfcEnabled) { 1482 return isSuccess; 1483 } 1484 1485 /* find the device in the hmap */ 1486 device = (NfcDepEndpoint) findObject(nativeHandle); 1487 if (device != null) { 1488 isSuccess = device.send(data); 1489 } 1490 return isSuccess; 1491 } 1492 }; 1493 1494 private final IP2pTarget mP2pTargetService = new IP2pTarget.Stub() { 1495 1496 @Override 1497 public int connect(int nativeHandle) throws RemoteException { 1498 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1499 1500 NfcDepEndpoint device; 1501 1502 // Check if NFC is enabled 1503 if (!mIsNfcEnabled) { 1504 return ErrorCodes.ERROR_NOT_INITIALIZED; 1505 } 1506 1507 /* find the device in the hmap */ 1508 device = (NfcDepEndpoint) findObject(nativeHandle); 1509 if (device != null) { 1510 if (device.connect()) { 1511 return ErrorCodes.SUCCESS; 1512 } 1513 } 1514 return ErrorCodes.ERROR_CONNECT; 1515 } 1516 1517 @Override 1518 public boolean disconnect(int nativeHandle) throws RemoteException { 1519 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1520 1521 NfcDepEndpoint device; 1522 boolean isSuccess = false; 1523 1524 // Check if NFC is enabled 1525 if (!mIsNfcEnabled) { 1526 return isSuccess; 1527 } 1528 1529 /* find the device in the hmap */ 1530 device = (NfcDepEndpoint) findObject(nativeHandle); 1531 if (device != null) { 1532 if (isSuccess = device.disconnect()) { 1533 /* remove the device from the hmap */ 1534 unregisterObject(nativeHandle); 1535 /* Restart polling loop for notification */ 1536 applyRouting(); 1537 } 1538 } 1539 return isSuccess; 1540 1541 } 1542 1543 @Override 1544 public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { 1545 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1546 1547 NfcDepEndpoint device; 1548 1549 // Check if NFC is enabled 1550 if (!mIsNfcEnabled) { 1551 return null; 1552 } 1553 1554 /* find the device in the hmap */ 1555 device = (NfcDepEndpoint) findObject(nativeHandle); 1556 if (device != null) { 1557 byte[] buff = device.getGeneralBytes(); 1558 if (buff == null) 1559 return null; 1560 return buff; 1561 } 1562 return null; 1563 } 1564 1565 @Override 1566 public int getMode(int nativeHandle) throws RemoteException { 1567 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1568 1569 NfcDepEndpoint device; 1570 1571 // Check if NFC is enabled 1572 if (!mIsNfcEnabled) { 1573 return ErrorCodes.ERROR_NOT_INITIALIZED; 1574 } 1575 1576 /* find the device in the hmap */ 1577 device = (NfcDepEndpoint) findObject(nativeHandle); 1578 if (device != null) { 1579 return device.getMode(); 1580 } 1581 return ErrorCodes.ERROR_INVALID_PARAM; 1582 } 1583 1584 @Override 1585 public byte[] transceive(int nativeHandle, byte[] data) 1586 throws RemoteException { 1587 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1588 1589 NfcDepEndpoint device; 1590 1591 // Check if NFC is enabled 1592 if (!mIsNfcEnabled) { 1593 return null; 1594 } 1595 1596 /* find the device in the hmap */ 1597 device = (NfcDepEndpoint) findObject(nativeHandle); 1598 if (device != null) { 1599 return device.transceive(data); 1600 } 1601 return null; 1602 } 1603 }; 1604 1605 private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException { 1606 // Blocks until a pending open() or transceive() times out. 1607 //TODO: This is incorrect behavior - the close should interrupt pending 1608 // operations. However this is not supported by current hardware. 1609 1610 synchronized(NfcService.this) { 1611 if (!mIsNfcEnabled) { 1612 throw new IOException("NFC adapter is disabled"); 1613 } 1614 if (mOpenEe == null) { 1615 throw new IOException("NFC EE closed"); 1616 } 1617 if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) { 1618 throw new SecurityException("Wrong PID"); 1619 } 1620 1621 mDeviceHost.resetTimeouts(); 1622 mSecureElement.doDisconnect(mOpenEe.handle); 1623 mOpenEe = null; 1624 1625 applyRouting(); 1626 } 1627 } 1628 1629 private INfcAdapterExtras mExtrasService = new INfcAdapterExtras.Stub() { 1630 private Bundle writeNoException() { 1631 Bundle p = new Bundle(); 1632 p.putInt("e", 0); 1633 return p; 1634 } 1635 private Bundle writeIoException(IOException e) { 1636 Bundle p = new Bundle(); 1637 p.putInt("e", -1); 1638 p.putString("m", e.getMessage()); 1639 return p; 1640 } 1641 1642 @Override 1643 public Bundle open(IBinder b) throws RemoteException { 1644 NfcService.enforceNfceeAdminPerm(mContext); 1645 1646 Bundle result; 1647 try { 1648 _open(b); 1649 result = writeNoException(); 1650 } catch (IOException e) { 1651 result = writeIoException(e); 1652 } 1653 return result; 1654 } 1655 1656 private void _open(IBinder b) throws IOException, RemoteException { 1657 synchronized(NfcService.this) { 1658 if (!mIsNfcEnabled) { 1659 throw new IOException("NFC adapter is disabled"); 1660 } 1661 if (mOpenEe != null) { 1662 throw new IOException("NFC EE already open"); 1663 } 1664 1665 int handle = mSecureElement.doOpenSecureElementConnection(); 1666 if (handle == 0) { 1667 throw new IOException("NFC EE failed to open"); 1668 } 1669 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1670 1671 mOpenEe = new OpenSecureElement(getCallingPid(), handle); 1672 try { 1673 b.linkToDeath(mOpenEe, 0); 1674 } catch (RemoteException e) { 1675 mOpenEe.binderDied(); 1676 } 1677 1678 // Add the calling package to the list of packages that have accessed 1679 // the secure element. 1680 for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 1681 mSePackages.add(packageName); 1682 } 1683 } 1684 } 1685 1686 @Override 1687 public Bundle close() throws RemoteException { 1688 NfcService.enforceNfceeAdminPerm(mContext); 1689 1690 Bundle result; 1691 try { 1692 _nfcEeClose(true, getCallingPid()); 1693 result = writeNoException(); 1694 } catch (IOException e) { 1695 result = writeIoException(e); 1696 } 1697 return result; 1698 } 1699 1700 @Override 1701 public Bundle transceive(byte[] in) throws RemoteException { 1702 NfcService.enforceNfceeAdminPerm(mContext); 1703 1704 Bundle result; 1705 byte[] out; 1706 try { 1707 out = _transceive(in); 1708 result = writeNoException(); 1709 result.putByteArray("out", out); 1710 } catch (IOException e) { 1711 result = writeIoException(e); 1712 } 1713 return result; 1714 } 1715 1716 private byte[] _transceive(byte[] data) throws IOException, RemoteException { 1717 synchronized(NfcService.this) { 1718 if (!mIsNfcEnabled) { 1719 throw new IOException("NFC is not enabled"); 1720 } 1721 if (mOpenEe == null){ 1722 throw new IOException("NFC EE is not open"); 1723 } 1724 if (getCallingPid() != mOpenEe.pid) { 1725 throw new SecurityException("Wrong PID"); 1726 } 1727 } 1728 1729 return mSecureElement.doTransceive(mOpenEe.handle, data); 1730 } 1731 1732 @Override 1733 public int getCardEmulationRoute() throws RemoteException { 1734 NfcService.enforceNfceeAdminPerm(mContext); 1735 return mEeRoutingState; 1736 } 1737 1738 @Override 1739 public void setCardEmulationRoute(int route) throws RemoteException { 1740 NfcService.enforceNfceeAdminPerm(mContext); 1741 mEeRoutingState = route; 1742 applyRouting(); 1743 } 1744 1745 @Override 1746 public void authenticate(byte[] token) throws RemoteException { 1747 NfcService.enforceNfceeAdminPerm(mContext); 1748 } 1749 }; 1750 1751 /** resources kept while secure element is open */ 1752 private class OpenSecureElement implements IBinder.DeathRecipient { 1753 public int pid; // pid that opened SE 1754 public int handle; // low-level handle 1755 public OpenSecureElement(int pid, int handle) { 1756 this.pid = pid; 1757 this.handle = handle; 1758 } 1759 @Override 1760 public void binderDied() { 1761 synchronized (NfcService.this) { 1762 if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 1763 pid = -1; 1764 try { 1765 _nfcEeClose(false, -1); 1766 } catch (IOException e) { /* already closed */ } 1767 } 1768 } 1769 } 1770 1771 private boolean _enable(boolean oldEnabledState, boolean savePref) { 1772 boolean isSuccess = mDeviceHost.initialize(); 1773 if (isSuccess) { 1774 mIsNfcEnabled = true; 1775 mIsDiscoveryOn = true; 1776 1777 /* Start polling loop */ 1778 applyRouting(); 1779 synchronized(NfcService.this) { 1780 boolean zeroclick_on = mPrefs.getBoolean(PREF_ZEROCLICK_ON, 1781 ZEROCLICK_ON_DEFAULT); 1782 if (zeroclick_on) { 1783 /* bring up p2p ndef servers */ 1784 mP2pManager.enableNdefServer(); 1785 mZeroClickOn = true; 1786 } 1787 } 1788 } else { 1789 Log.w(TAG, "Error enabling NFC"); 1790 mIsNfcEnabled = false; 1791 } 1792 1793 if (savePref) { 1794 updateNfcOnSetting(oldEnabledState); 1795 } 1796 1797 return isSuccess; 1798 } 1799 1800 private boolean _disable(boolean oldEnabledState, boolean savePref) { 1801 /* sometimes mDeviceHost.deinitialize() hangs, watch-dog it */ 1802 WatchDogThread watchDog = new WatchDogThread(); 1803 watchDog.start(); 1804 1805 boolean isSuccess; 1806 1807 /* tear down the p2p server */ 1808 synchronized(NfcService.this) { 1809 if (mZeroClickOn) { 1810 mP2pManager.disableNdefServer(); 1811 mZeroClickOn = false; 1812 } 1813 } 1814 // Stop watchdog if tag present 1815 // A convenient way to stop the watchdog properly consists of 1816 // disconnecting the tag. The polling loop shall be stopped before 1817 // to avoid the tag being discovered again. 1818 mIsDiscoveryOn = false; 1819 applyRouting(); 1820 maybeDisconnectTarget(); 1821 1822 isSuccess = mDeviceHost.deinitialize(); 1823 if (DBG) Log.d(TAG, "NFC success of deinitialize = " + isSuccess); 1824 if (isSuccess) { 1825 mIsNfcEnabled = false; 1826 mNfcDispatcher.disableForegroundDispatch(); 1827 mP2pManager.setForegroundMessage(null); 1828 } 1829 1830 if (savePref) { 1831 updateNfcOnSetting(oldEnabledState); 1832 } 1833 1834 watchDog.cancel(); 1835 return isSuccess; 1836 } 1837 1838 private class WatchDogThread extends Thread { 1839 boolean mWatchDogCanceled = false; 1840 @Override 1841 public void run() { 1842 boolean slept = false; 1843 while (!slept) { 1844 try { 1845 Thread.sleep(10000); 1846 slept = true; 1847 } catch (InterruptedException e) { } 1848 } 1849 synchronized (this) { 1850 if (!mWatchDogCanceled) { 1851 // Trigger watch-dog 1852 Log.e(TAG, "Watch dog triggered"); 1853 mDeviceHost.doAbort(); 1854 } 1855 } 1856 } 1857 public synchronized void cancel() { 1858 mWatchDogCanceled = true; 1859 } 1860 } 1861 1862 /** apply NFC discovery and EE routing */ 1863 private synchronized void applyRouting() { 1864 if (mIsNfcEnabled && mOpenEe == null) { 1865 if (mScreenUnlocked) { 1866 if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1867 Log.d(TAG, "NFC-EE routing ON"); 1868 mDeviceHost.doSelectSecureElement(); 1869 } else { 1870 Log.d(TAG, "NFC-EE routing OFF"); 1871 mDeviceHost.doDeselectSecureElement(); 1872 } 1873 if (mIsDiscoveryOn) { 1874 Log.d(TAG, "NFC-C discovery ON"); 1875 mDeviceHost.enableDiscovery(); 1876 } else { 1877 Log.d(TAG, "NFC-C discovery OFF"); 1878 mDeviceHost.disableDiscovery(); 1879 } 1880 } else { 1881 Log.d(TAG, "NFC-EE routing OFF"); 1882 mDeviceHost.doDeselectSecureElement(); 1883 Log.d(TAG, "NFC-C discovery OFF"); 1884 mDeviceHost.disableDiscovery(); 1885 } 1886 } 1887 } 1888 1889 /** Disconnect any target if present */ 1890 private synchronized void maybeDisconnectTarget() { 1891 if (mIsNfcEnabled) { 1892 Iterator<?> iterator = mObjectMap.values().iterator(); 1893 while(iterator.hasNext()) { 1894 Object object = iterator.next(); 1895 if (object instanceof TagEndpoint) { 1896 // Disconnect from tags 1897 TagEndpoint tag = (TagEndpoint) object; 1898 tag.disconnect(); 1899 } else if(object instanceof NfcDepEndpoint) { 1900 // Disconnect from P2P devices 1901 NfcDepEndpoint device = (NfcDepEndpoint) object; 1902 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1903 // Remote peer is target, request disconnection 1904 device.disconnect(); 1905 } else { 1906 // Remote peer is initiator, we cannot disconnect 1907 // Just wait for field removal 1908 } 1909 } 1910 iterator.remove(); 1911 } 1912 } 1913 } 1914 1915 //TODO: dont hardcode this 1916 private static final byte[][] SE_RESET_APDUS = { 1917 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 1918 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 1919 {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 1920 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 1921 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 1922 {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 1923 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 1924 }; 1925 1926 private void resetSeOnFirstBoot() { 1927 if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 1928 Log.i(TAG, "First Boot"); 1929 mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 1930 mPrefsEditor.apply(); 1931 executeSeReset(); 1932 } 1933 } 1934 1935 private synchronized void executeSeReset() { 1936 // TODO: read SE reset list from /system/etc 1937 //List<byte[]> apdus = readSeResetApdus(); 1938 byte[][]apdus = SE_RESET_APDUS; 1939 if (apdus == null) { 1940 return; 1941 } 1942 1943 boolean tempEnable = !mIsNfcEnabled; 1944 if (tempEnable) { 1945 if (!_enable(false, false)) { 1946 Log.w(TAG, "Could not enable NFC to reset EE!"); 1947 return; 1948 } 1949 } 1950 1951 Log.i(TAG, "Executing SE Reset Script"); 1952 int handle = mSecureElement.doOpenSecureElementConnection(); 1953 if (handle == 0) { 1954 Log.e(TAG, "Could not open the secure element!"); 1955 if (tempEnable) { 1956 _disable(true, false); 1957 } 1958 return; 1959 } 1960 1961 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1962 1963 for (byte[] cmd : apdus) { 1964 mSecureElement.doTransceive(handle, cmd); 1965 } 1966 1967 mDeviceHost.resetTimeouts(); 1968 1969 mSecureElement.doDisconnect(handle); 1970 1971 if (tempEnable) { 1972 _disable(true, false); 1973 } 1974 } 1975 1976 private List<byte[]> readSeResetApdus() { 1977 FileInputStream input = null; 1978 List<byte[]> apdus = null; 1979 1980 try { 1981 input = openFileInput(SE_RESET_SCRIPT_FILE_NAME); 1982 DataInputStream stream = new DataInputStream(input); 1983 1984 int commandsSize = stream.readInt(); 1985 apdus = new ArrayList<byte[]>(commandsSize); 1986 1987 for (int i = 0 ; i < commandsSize ; i++) { 1988 int length = stream.readInt(); 1989 1990 byte[] cmd = new byte[length]; 1991 1992 stream.read(cmd); 1993 apdus.add(cmd); 1994 } 1995 1996 return apdus; 1997 } catch (FileNotFoundException e) { 1998 Log.e(TAG, "SE Reset Script not found: " + SE_RESET_SCRIPT_FILE_NAME); 1999 } catch (IOException e) { 2000 Log.e(TAG, "SE Reset Script corrupt: ", e); 2001 apdus = null; 2002 } finally { 2003 try { 2004 if (input != null) { 2005 input.close(); 2006 } 2007 } catch (IOException e) { 2008 // Ignore 2009 } 2010 } 2011 return apdus; 2012 } 2013 2014 private void updateNfcOnSetting(boolean oldEnabledState) { 2015 mPrefsEditor.putBoolean(PREF_NFC_ON, mIsNfcEnabled); 2016 mPrefsEditor.apply(); 2017 2018 synchronized(this) { 2019 if (oldEnabledState != mIsNfcEnabled) { 2020 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGE); 2021 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2022 intent.putExtra(NfcAdapter.EXTRA_NEW_BOOLEAN_STATE, mIsNfcEnabled); 2023 mContext.sendBroadcast(intent); 2024 } 2025 } 2026 } 2027 2028 // Reset all internals 2029 private synchronized void reset() { 2030 // TODO: none of these appear to be synchronized but are 2031 // read/written from different threads (notably Binder threads)... 2032 2033 // Clear tables 2034 mObjectMap.clear(); 2035 mSocketMap.clear(); 2036 2037 // Reset variables 2038 mIsNfcEnabled = false; 2039 } 2040 2041 private synchronized Object findObject(int key) { 2042 Object device = null; 2043 2044 device = mObjectMap.get(key); 2045 if (device == null) { 2046 Log.w(TAG, "Handle not found !"); 2047 } 2048 2049 return device; 2050 } 2051 2052 synchronized void registerTagObject(TagEndpoint tag) { 2053 mObjectMap.put(tag.getHandle(), tag); 2054 } 2055 2056 synchronized void unregisterObject(int handle) { 2057 mObjectMap.remove(handle); 2058 } 2059 2060 private synchronized Object findSocket(int key) { 2061 if (mSocketMap == null) { 2062 return null; 2063 } 2064 return mSocketMap.get(key); 2065 } 2066 2067 private void removeSocket(int key) { 2068 mSocketMap.remove(key); 2069 } 2070 2071 /** For use by code in this process */ 2072 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) { 2073 try { 2074 int handle = mNfcAdapter.createLlcpSocket(sap, miu, rw, linearBufferLength); 2075 if (ErrorCodes.isError(handle)) { 2076 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2077 return null; 2078 } 2079 return new LlcpSocket(mLlcpSocket, handle); 2080 } catch (RemoteException e) { 2081 // This will never happen since the code is calling into it's own process 2082 throw new IllegalStateException("unable to talk to myself", e); 2083 } 2084 } 2085 2086 /** For use by code in this process */ 2087 public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw, 2088 int linearBufferLength) { 2089 try { 2090 int handle = mNfcAdapter.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); 2091 if (ErrorCodes.isError(handle)) { 2092 Log.e(TAG, "unable to create socket: " + ErrorCodes.asString(handle)); 2093 return null; 2094 } 2095 return new LlcpServiceSocket(mLlcpServerSocketService, mLlcpSocket, handle); 2096 } catch (RemoteException e) { 2097 // This will never happen since the code is calling into it's own process 2098 throw new IllegalStateException("unable to talk to myself", e); 2099 } 2100 } 2101 2102 public void sendMockNdefTag(NdefMessage msg) { 2103 sendMessage(MSG_MOCK_NDEF, msg); 2104 } 2105 2106 public void sendMeProfile(NdefMessage target, NdefMessage profile) { 2107 mP2pManager.sendMeProfile(target, profile); 2108 } 2109 2110 void sendMessage(int what, Object obj) { 2111 Message msg = mHandler.obtainMessage(); 2112 msg.what = what; 2113 msg.obj = obj; 2114 mHandler.sendMessage(msg); 2115 } 2116 2117 final class NfcServiceHandler extends Handler { 2118 @Override 2119 public void handleMessage(Message msg) { 2120 switch (msg.what) { 2121 case MSG_MOCK_NDEF: { 2122 NdefMessage ndefMsg = (NdefMessage) msg.obj; 2123 Bundle extras = new Bundle(); 2124 extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 2125 extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 2126 extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 2127 extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 2128 Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 2129 new int[] { TagTechnology.NDEF }, 2130 new Bundle[] { extras }); 2131 Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 2132 Log.d(TAG, tag.toString()); 2133 boolean delivered = mNfcDispatcher.dispatchTag(tag, new NdefMessage[] { ndefMsg }); 2134 if (delivered) { 2135 playSound(mEndSound); 2136 } else { 2137 playSound(mErrorSound); 2138 } 2139 break; 2140 } 2141 2142 case MSG_NDEF_TAG: 2143 if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 2144 TagEndpoint tag = (TagEndpoint) msg.obj; 2145 playSound(mStartSound); 2146 NdefMessage[] ndefMsgs = tag.findAndReadNdef(); 2147 2148 if (ndefMsgs != null) { 2149 tag.startPresenceChecking(); 2150 dispatchTagEndpoint(tag, ndefMsgs); 2151 } else { 2152 if (tag.reconnect()) { 2153 tag.startPresenceChecking(); 2154 dispatchTagEndpoint(tag, null); 2155 } else { 2156 tag.disconnect(); 2157 } 2158 } 2159 break; 2160 2161 case MSG_CARD_EMULATION: 2162 if (DBG) Log.d(TAG, "Card Emulation message"); 2163 byte[] aid = (byte[]) msg.obj; 2164 /* Send broadcast */ 2165 Intent aidIntent = new Intent(); 2166 aidIntent.setAction(ACTION_AID_SELECTED); 2167 aidIntent.putExtra(EXTRA_AID, aid); 2168 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 2169 mContext.sendBroadcast(aidIntent, NFCEE_ADMIN_PERM); 2170 break; 2171 2172 case MSG_SE_EMV_CARD_REMOVAL: 2173 if (DBG) Log.d(TAG, "Card Removal message"); 2174 /* Send broadcast */ 2175 Intent cardRemovalIntent = new Intent(); 2176 cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 2177 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 2178 mContext.sendBroadcast(cardRemovalIntent, NFCEE_ADMIN_PERM); 2179 break; 2180 2181 case MSG_SE_APDU_RECEIVED: 2182 if (DBG) Log.d(TAG, "APDU Received message"); 2183 byte[] apduBytes = (byte[]) msg.obj; 2184 /* Send broadcast */ 2185 Intent apduReceivedIntent = new Intent(); 2186 apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 2187 if (apduBytes != null && apduBytes.length > 0) { 2188 apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 2189 } 2190 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 2191 mContext.sendBroadcast(apduReceivedIntent, NFCEE_ADMIN_PERM); 2192 break; 2193 2194 case MSG_SE_MIFARE_ACCESS: 2195 if (DBG) Log.d(TAG, "MIFARE access message"); 2196 /* Send broadcast */ 2197 byte[] mifareCmd = (byte[]) msg.obj; 2198 Intent mifareAccessIntent = new Intent(); 2199 mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 2200 if (mifareCmd != null && mifareCmd.length > 1) { 2201 int mifareBlock = mifareCmd[1] & 0xff; 2202 if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 2203 mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 2204 } 2205 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 2206 mContext.sendBroadcast(mifareAccessIntent, NFCEE_ADMIN_PERM); 2207 break; 2208 2209 case MSG_LLCP_LINK_ACTIVATION: 2210 if (llcpActivated((NfcDepEndpoint) msg.obj)) { 2211 playSound(mStartSound); 2212 } else { 2213 playSound(mErrorSound); 2214 } 2215 break; 2216 2217 case MSG_LLCP_LINK_DEACTIVATED: 2218 NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 2219 2220 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 2221 synchronized (NfcService.this) { 2222 /* Check if the device has been already unregistered */ 2223 if (mObjectMap.remove(device.getHandle()) != null) { 2224 /* Disconnect if we are initiator */ 2225 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 2226 if (DBG) Log.d(TAG, "disconnecting from target"); 2227 /* Restart polling loop */ 2228 device.disconnect(); 2229 } else { 2230 if (DBG) Log.d(TAG, "not disconnecting from initiator"); 2231 } 2232 } 2233 } 2234 2235 mP2pManager.llcpDeactivated(); 2236 break; 2237 2238 case MSG_TARGET_DESELECTED: 2239 /* Broadcast Intent Target Deselected */ 2240 if (DBG) Log.d(TAG, "Target Deselected"); 2241 Intent intent = new Intent(); 2242 intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 2243 if (DBG) Log.d(TAG, "Broadcasting Intent"); 2244 mContext.sendOrderedBroadcast(intent, NFC_PERM); 2245 break; 2246 2247 case MSG_SE_FIELD_ACTIVATED:{ 2248 if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 2249 Intent eventFieldOnIntent = new Intent(); 2250 eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 2251 mContext.sendBroadcast(eventFieldOnIntent, NFCEE_ADMIN_PERM); 2252 break; 2253 } 2254 2255 case MSG_SE_FIELD_DEACTIVATED:{ 2256 if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 2257 Intent eventFieldOffIntent = new Intent(); 2258 eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 2259 mContext.sendBroadcast(eventFieldOffIntent, NFCEE_ADMIN_PERM); 2260 break; 2261 } 2262 2263 default: 2264 Log.e(TAG, "Unknown message received"); 2265 break; 2266 } 2267 } 2268 2269 private boolean llcpActivated(NfcDepEndpoint device) { 2270 Log.d(TAG, "LLCP Activation message"); 2271 2272 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 2273 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 2274 if (device.connect()) { 2275 /* Check LLCP compliancy */ 2276 if (mDeviceHost.doCheckLlcp()) { 2277 /* Activate LLCP Link */ 2278 if (mDeviceHost.doActivateLlcp()) { 2279 if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 2280 // Register P2P device 2281 mObjectMap.put(device.getHandle(), device); 2282 // TODO this should be done decently instead, not depend on the bool 2283 if (mZeroClickOn) { 2284 mP2pManager.llcpActivated(); 2285 } 2286 return true; 2287 } else { 2288 /* should not happen */ 2289 Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 2290 device.disconnect(); 2291 } 2292 } else { 2293 if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 2294 device.disconnect(); 2295 } 2296 } else { 2297 if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 2298 /* 2299 * The polling loop should have been restarted in failing 2300 * doConnect 2301 */ 2302 } 2303 } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 2304 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 2305 /* Check LLCP compliancy */ 2306 if (mDeviceHost.doCheckLlcp()) { 2307 /* Activate LLCP Link */ 2308 if (mDeviceHost.doActivateLlcp()) { 2309 if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 2310 // Register P2P device 2311 mObjectMap.put(device.getHandle(), device); 2312 // TODO this should be done decently instead, not depend on the bool 2313 if (mZeroClickOn) { 2314 mP2pManager.llcpActivated(); 2315 } 2316 return true; 2317 } 2318 } else { 2319 Log.w(TAG, "checkLlcp failed"); 2320 } 2321 } 2322 2323 return false; 2324 } 2325 2326 private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) { 2327 Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 2328 tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 2329 registerTagObject(tagEndpoint); 2330 if (!mNfcDispatcher.dispatchTag(tag, msgs)) { 2331 unregisterObject(tagEndpoint.getHandle()); 2332 playSound(mErrorSound); 2333 } else { 2334 playSound(mEndSound); 2335 } 2336 } 2337 } 2338 2339 private NfcServiceHandler mHandler = new NfcServiceHandler(); 2340 2341 private class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 2342 @Override 2343 protected Void doInBackground(Boolean... params) { 2344 if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]); 2345 2346 if (params != null && params.length > 0 && params[0]) { 2347 synchronized (NfcService.this) { 2348 if (!mScreenUnlocked) { 2349 mScreenUnlocked = true; 2350 applyRouting(); 2351 } else { 2352 if (DBG) Log.d(TAG, "Ignoring enable request"); 2353 } 2354 } 2355 } else { 2356 mWakeLock.acquire(); 2357 synchronized (NfcService.this) { 2358 if (mScreenUnlocked) { 2359 mScreenUnlocked = false; 2360 applyRouting(); 2361 maybeDisconnectTarget(); 2362 } else { 2363 if (DBG) Log.d(TAG, "Ignoring disable request"); 2364 } 2365 } 2366 mWakeLock.release(); 2367 } 2368 return null; 2369 } 2370 } 2371 2372 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2373 @Override 2374 public void onReceive(Context context, Intent intent) { 2375 if (intent.getAction().equals( 2376 NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 2377 if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 2378 2379 /* Restart polling loop for notification */ 2380 applyRouting(); 2381 2382 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 2383 // Only enable if the screen is unlocked. If the screen is locked 2384 // Intent.ACTION_USER_PRESENT will be broadcast when the screen is 2385 // unlocked. 2386 boolean enable = !mKeyguard.isKeyguardSecure() || !mKeyguard.isKeyguardLocked(); 2387 2388 // Perform discovery enable in thread to protect against ANR when the 2389 // NFC stack wedges. This is *not* the correct way to fix this issue - 2390 // configuration of the local NFC adapter should be very quick and should 2391 // be safe on the main thread, and the NFC stack should not wedge. 2392 new EnableDisableDiscoveryTask().execute(enable); 2393 } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 2394 // Perform discovery disable in thread to protect against ANR when the 2395 // NFC stack wedges. This is *not* the correct way to fix this issue - 2396 // configuration of the local NFC adapter should be very quick and should 2397 // be safe on the main thread, and the NFC stack should not wedge. 2398 new EnableDisableDiscoveryTask().execute(Boolean.FALSE); 2399 } else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) { 2400 // The user has unlocked the screen. Enabled! 2401 new EnableDisableDiscoveryTask().execute(Boolean.TRUE); 2402 } else if (intent.getAction().equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 2403 executeSeReset(); 2404 } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) { 2405 boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 2406 if (dataRemoved) { 2407 Uri data = intent.getData(); 2408 if (data == null) return; 2409 String packageName = data.getSchemeSpecificPart(); 2410 2411 synchronized (NfcService.this) { 2412 if (mSePackages.contains(packageName)) { 2413 executeSeReset(); 2414 mSePackages.remove(packageName); 2415 } 2416 } 2417 } 2418 } 2419 } 2420 }; 2421} 2422