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