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