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