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 17 package com.android.nfc; 18 19 import com.android.nfc.DeviceHost.DeviceHostListener; 20 import com.android.nfc.DeviceHost.LlcpServerSocket; 21 import com.android.nfc.DeviceHost.LlcpSocket; 22 import com.android.nfc.DeviceHost.NfcDepEndpoint; 23 import com.android.nfc.DeviceHost.TagEndpoint; 24 import com.android.nfc.nxp.NativeNfcManager; 25 import com.android.nfc.nxp.NativeNfcSecureElement; 26 import com.android.nfc3.R; 27 28 import android.app.Application; 29 import android.app.KeyguardManager; 30 import android.app.PendingIntent; 31 import android.content.BroadcastReceiver; 32 import android.content.ComponentName; 33 import android.content.ContentResolver; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.SharedPreferences; 38 import android.content.pm.PackageManager; 39 import android.media.AudioManager; 40 import android.media.SoundPool; 41 import android.net.Uri; 42 import android.nfc.ErrorCodes; 43 import android.nfc.FormatException; 44 import android.nfc.INdefPushCallback; 45 import android.nfc.INfcAdapter; 46 import android.nfc.INfcAdapterExtras; 47 import android.nfc.INfcTag; 48 import android.nfc.NdefMessage; 49 import android.nfc.NfcAdapter; 50 import android.nfc.Tag; 51 import android.nfc.TechListParcel; 52 import android.nfc.TransceiveResult; 53 import android.nfc.tech.Ndef; 54 import android.nfc.tech.TagTechnology; 55 import android.os.AsyncTask; 56 import android.os.Binder; 57 import android.os.Bundle; 58 import android.os.Handler; 59 import android.os.IBinder; 60 import android.os.Message; 61 import android.os.PowerManager; 62 import android.os.Process; 63 import android.os.RemoteException; 64 import android.os.ServiceManager; 65 import android.provider.Settings; 66 import android.util.Log; 67 68 import java.io.FileDescriptor; 69 import java.io.IOException; 70 import java.io.PrintWriter; 71 import java.util.Arrays; 72 import java.util.HashMap; 73 import java.util.HashSet; 74 import java.util.concurrent.ExecutionException; 75 76 public class NfcService extends Application implements DeviceHostListener { 77 private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION"; 78 79 static final boolean DBG = true; 80 static final String TAG = "NfcService"; 81 82 public static final String SERVICE_NAME = "nfc"; 83 84 private static final String NFC_PERM = android.Manifest.permission.NFC; 85 private static final String NFC_PERM_ERROR = "NFC permission required"; 86 private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 87 private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 88 private static final String NFCEE_ADMIN_PERM = "com.android.nfc.permission.NFCEE_ADMIN"; 89 private static final String NFCEE_ADMIN_PERM_ERROR = "NFCEE_ADMIN permission required"; 90 91 public static final String PREF = "NfcServicePrefs"; 92 93 private static final String PREF_NFC_ON = "nfc_on"; 94 private static final boolean NFC_ON_DEFAULT = true; 95 private static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 96 private static final boolean NDEF_PUSH_ON_DEFAULT = true; 97 98 private static final String PREF_FIRST_BOOT = "first_boot"; 99 100 static final int MSG_NDEF_TAG = 0; 101 static final int MSG_CARD_EMULATION = 1; 102 static final int MSG_LLCP_LINK_ACTIVATION = 2; 103 static final int MSG_LLCP_LINK_DEACTIVATED = 3; 104 static final int MSG_TARGET_DESELECTED = 4; 105 static final int MSG_MOCK_NDEF = 7; 106 static final int MSG_SE_FIELD_ACTIVATED = 8; 107 static final int MSG_SE_FIELD_DEACTIVATED = 9; 108 static final int MSG_SE_APDU_RECEIVED = 10; 109 static final int MSG_SE_EMV_CARD_REMOVAL = 11; 110 static final int MSG_SE_MIFARE_ACCESS = 12; 111 112 static final int TASK_ENABLE = 1; 113 static final int TASK_DISABLE = 2; 114 static final int TASK_BOOT = 3; 115 static final int TASK_EE_WIPE = 4; 116 117 // Copied from com.android.nfc_extras to avoid library dependency 118 // Must keep in sync with com.android.nfc_extras 119 static final int ROUTE_OFF = 1; 120 static final int ROUTE_ON_WHEN_SCREEN_ON = 2; 121 122 public static final String ACTION_RF_FIELD_ON_DETECTED = 123 "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED"; 124 public static final String ACTION_RF_FIELD_OFF_DETECTED = 125 "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED"; 126 public static final String ACTION_AID_SELECTED = 127 "com.android.nfc_extras.action.AID_SELECTED"; 128 public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; 129 130 public static final String ACTION_APDU_RECEIVED = 131 "com.android.nfc_extras.action.APDU_RECEIVED"; 132 public static final String EXTRA_APDU_BYTES = 133 "com.android.nfc_extras.extra.APDU_BYTES"; 134 135 public static final String ACTION_EMV_CARD_REMOVAL = 136 "com.android.nfc_extras.action.EMV_CARD_REMOVAL"; 137 138 public static final String ACTION_MIFARE_ACCESS_DETECTED = 139 "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED"; 140 public static final String EXTRA_MIFARE_BLOCK = 141 "com.android.nfc_extras.extra.MIFARE_BLOCK"; 142 143 //TODO: dont hardcode this 144 private static final byte[][] EE_WIPE_APDUS = { 145 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 146 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 147 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 148 {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 149 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 150 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 151 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 152 {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 153 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 154 }; 155 156 // NFC Execution Environment 157 // fields below are protected by this 158 private NativeNfcSecureElement mSecureElement; 159 private OpenSecureElement mOpenEe; // null when EE closed 160 private int mEeRoutingState; // contactless interface routing 161 162 // fields below must be used only on the UI thread and therefore aren't synchronized 163 boolean mP2pStarted = false; 164 165 // fields below are used in multiple threads and protected by synchronized(this) 166 private final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 167 private HashSet<String> mSePackages = new HashSet<String>(); 168 private boolean mIsScreenUnlocked; 169 private boolean mIsNdefPushEnabled; 170 171 // mState is protected by this, however it is only modified in onCreate() 172 // and the default AsyncTask thread so it is read unprotected from that 173 // thread 174 int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 175 176 // fields below are final after onCreate() 177 Context mContext; 178 private DeviceHost mDeviceHost; 179 private SharedPreferences mPrefs; 180 private SharedPreferences.Editor mPrefsEditor; 181 private PowerManager.WakeLock mWakeLock; 182 int mStartSound; 183 int mEndSound; 184 int mErrorSound; 185 SoundPool mSoundPool; // playback synchronized on this 186 P2pLinkManager mP2pLinkManager; 187 TagService mNfcTagService; 188 NfcAdapterService mNfcAdapter; 189 NfcAdapterExtrasService mExtrasService; 190 boolean mIsAirplaneSensitive; 191 boolean mIsAirplaneToggleable; 192 193 private NfcDispatcher mNfcDispatcher; 194 private KeyguardManager mKeyguard; 195 196 private static NfcService sService; 197 198 public static void enforceAdminPerm(Context context) { 199 int admin = context.checkCallingOrSelfPermission(ADMIN_PERM); 200 int nfcee = context.checkCallingOrSelfPermission(NFCEE_ADMIN_PERM); 201 if (admin != PackageManager.PERMISSION_GRANTED 202 && nfcee != PackageManager.PERMISSION_GRANTED) { 203 throw new SecurityException(ADMIN_PERM_ERROR); 204 } 205 } 206 207 public static void enforceNfceeAdminPerm(Context context) { 208 context.enforceCallingOrSelfPermission(NFCEE_ADMIN_PERM, NFCEE_ADMIN_PERM_ERROR); 209 } 210 211 public static NfcService getInstance() { 212 return sService; 213 } 214 215 @Override 216 public void onRemoteEndpointDiscovered(TagEndpoint tag) { 217 sendMessage(NfcService.MSG_NDEF_TAG, tag); 218 } 219 220 /** 221 * Notifies transaction 222 */ 223 @Override 224 public void onCardEmulationDeselected() { 225 sendMessage(NfcService.MSG_TARGET_DESELECTED, null); 226 } 227 228 /** 229 * Notifies transaction 230 */ 231 @Override 232 public void onCardEmulationAidSelected(byte[] aid) { 233 sendMessage(NfcService.MSG_CARD_EMULATION, aid); 234 } 235 236 /** 237 * Notifies P2P Device detected, to activate LLCP link 238 */ 239 @Override 240 public void onLlcpLinkActivated(NfcDepEndpoint device) { 241 sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 242 } 243 244 /** 245 * Notifies P2P Device detected, to activate LLCP link 246 */ 247 @Override 248 public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 249 sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 250 } 251 252 @Override 253 public void onRemoteFieldActivated() { 254 sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null); 255 } 256 257 @Override 258 public void onRemoteFieldDeactivated() { 259 sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null); 260 } 261 262 @Override 263 public void onSeApduReceived(byte[] apdu) { 264 sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu); 265 } 266 267 @Override 268 public void onSeEmvCardRemoval() { 269 sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null); 270 } 271 272 @Override 273 public void onSeMifareAccess(byte[] block) { 274 sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block); 275 } 276 277 @Override 278 public void onCreate() { 279 super.onCreate(); 280 281 mNfcTagService = new TagService(); 282 mNfcAdapter = new NfcAdapterService(); 283 mExtrasService = new NfcAdapterExtrasService(); 284 285 Log.i(TAG, "Starting NFC service"); 286 287 sService = this; 288 289 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 290 mStartSound = mSoundPool.load(this, R.raw.start, 1); 291 mEndSound = mSoundPool.load(this, R.raw.end, 1); 292 mErrorSound = mSoundPool.load(this, R.raw.error, 1); 293 294 mContext = this; 295 mDeviceHost = new NativeNfcManager(this, this); 296 297 mP2pLinkManager = new P2pLinkManager(mContext); 298 mNfcDispatcher = new NfcDispatcher(this, mP2pLinkManager); 299 300 mSecureElement = new NativeNfcSecureElement(); 301 mEeRoutingState = ROUTE_OFF; 302 303 mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE); 304 mPrefsEditor = mPrefs.edit(); 305 306 mState = NfcAdapter.STATE_OFF; 307 mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 308 309 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 310 311 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService"); 312 mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 313 mIsScreenUnlocked = pm.isScreenOn() && !mKeyguard.isKeyguardLocked(); 314 315 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 316 317 IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 318 filter.addAction(Intent.ACTION_SCREEN_OFF); 319 filter.addAction(Intent.ACTION_SCREEN_ON); 320 filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION); 321 filter.addAction(Intent.ACTION_USER_PRESENT); 322 registerForAirplaneMode(filter); 323 registerReceiver(mReceiver, filter); 324 325 filter = new IntentFilter(); 326 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 327 filter.addDataScheme("package"); 328 329 registerReceiver(mReceiver, filter); 330 331 new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 332 } 333 334 void registerForAirplaneMode(IntentFilter filter) { 335 final ContentResolver resolver = mContext.getContentResolver(); 336 final String airplaneModeRadios = Settings.System.getString(resolver, 337 Settings.System.AIRPLANE_MODE_RADIOS); 338 final String toggleableRadios = Settings.System.getString(resolver, 339 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 340 341 mIsAirplaneSensitive = airplaneModeRadios == null ? true : 342 airplaneModeRadios.contains(Settings.System.RADIO_NFC); 343 mIsAirplaneToggleable = toggleableRadios == null ? false : 344 toggleableRadios.contains(Settings.System.RADIO_NFC); 345 346 if (mIsAirplaneSensitive) { 347 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 348 } 349 } 350 351 /** 352 * Manages tasks that involve turning on/off the NFC controller. 353 * 354 * <p>All work that might turn the NFC adapter on or off must be done 355 * through this task, to keep the handling of mState simple. 356 * In other words, mState is only modified in these tasks (and we 357 * don't need a lock to read it in these tasks). 358 * 359 * <p>These tasks are all done on the same AsyncTask background 360 * thread, so they are serialized. Each task may temporarily transition 361 * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 362 * either STATE_ON or STATE_OFF. This way each task can be guaranteed 363 * of starting in either STATE_OFF or STATE_ON, without needing to hold 364 * NfcService.this for the entire task. 365 * 366 * <p>AsyncTask's are also implicitly queued. This is useful for corner 367 * cases like turning airplane mode on while TASK_ENABLE is in progress. 368 * The TASK_DISABLE triggered by airplane mode will be correctly executed 369 * immediately after TASK_ENABLE is complete. This seems like the most sane 370 * way to deal with these situations. 371 * 372 * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 373 * preferences 374 * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 375 * preferences 376 * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 377 * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the 378 * process may temporarily enable the NFC adapter 379 */ 380 class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 381 @Override 382 protected Void doInBackground(Integer... params) { 383 // Sanity check mState 384 switch (mState) { 385 case NfcAdapter.STATE_TURNING_OFF: 386 case NfcAdapter.STATE_TURNING_ON: 387 Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 388 mState); 389 return null; 390 } 391 392 /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 393 * override with the default. THREAD_PRIORITY_BACKGROUND causes 394 * us to service software I2C too slow for firmware download 395 * with the NXP PN544. 396 * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 397 * problem only occurs on I2C platforms using PN544 398 */ 399 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 400 401 switch (params[0].intValue()) { 402 case TASK_ENABLE: 403 enableInternal(); 404 break; 405 case TASK_DISABLE: 406 disableInternal(); 407 break; 408 case TASK_BOOT: 409 Log.d(TAG,"checking on firmware download"); 410 if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 411 !(mIsAirplaneSensitive && isAirplaneModeOn())) { 412 Log.d(TAG,"NFC is on. Doing normal stuff"); 413 enableInternal(); 414 } else { 415 Log.d(TAG,"NFC is off. Checking firmware version"); 416 mDeviceHost.checkFirmware(); 417 } 418 if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 419 Log.i(TAG, "First Boot"); 420 mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 421 mPrefsEditor.apply(); 422 executeEeWipe(); 423 } 424 break; 425 case TASK_EE_WIPE: 426 executeEeWipe(); 427 break; 428 } 429 430 // Restore default AsyncTask priority 431 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 432 return null; 433 } 434 435 /** 436 * Enable NFC adapter functions. 437 * Does not toggle preferences. 438 */ 439 boolean enableInternal() { 440 if (mState == NfcAdapter.STATE_ON) { 441 return true; 442 } 443 Log.i(TAG, "Enabling NFC"); 444 updateState(NfcAdapter.STATE_TURNING_ON); 445 446 if (!mDeviceHost.initialize()) { 447 Log.w(TAG, "Error enabling NFC"); 448 updateState(NfcAdapter.STATE_OFF); 449 return false; 450 } 451 452 synchronized(NfcService.this) { 453 mObjectMap.clear(); 454 455 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 456 updateState(NfcAdapter.STATE_ON); 457 } 458 459 /* Start polling loop */ 460 applyRouting(); 461 return true; 462 } 463 464 /** 465 * Disable all NFC adapter functions. 466 * Does not toggle preferences. 467 */ 468 boolean disableInternal() { 469 if (mState == NfcAdapter.STATE_OFF) { 470 return true; 471 } 472 Log.i(TAG, "Disabling NFC"); 473 updateState(NfcAdapter.STATE_TURNING_OFF); 474 475 /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 476 * Implemented with a new thread (instead of a Handler or AsyncTask), 477 * because the UI Thread and AsyncTask thread-pools can also get hung 478 * when the NFC controller stops responding */ 479 WatchDogThread watchDog = new WatchDogThread(); 480 watchDog.start(); 481 482 mP2pLinkManager.enableDisable(false, false); 483 484 // Stop watchdog if tag present 485 // A convenient way to stop the watchdog properly consists of 486 // disconnecting the tag. The polling loop shall be stopped before 487 // to avoid the tag being discovered again. 488 applyRouting(); 489 maybeDisconnectTarget(); 490 491 mNfcDispatcher.setForegroundDispatch(null, null, null); 492 493 boolean result = mDeviceHost.deinitialize(); 494 if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 495 496 watchDog.cancel(); 497 498 updateState(NfcAdapter.STATE_OFF); 499 500 return result; 501 } 502 503 void executeEeWipe() { 504 // TODO: read SE reset list from /system/etc 505 byte[][]apdus = EE_WIPE_APDUS; 506 507 boolean tempEnable = mState == NfcAdapter.STATE_OFF; 508 if (tempEnable) { 509 if (!enableInternal()) { 510 Log.w(TAG, "Could not enable NFC to wipe NFC-EE"); 511 return; 512 } 513 } 514 Log.i(TAG, "Executing SE wipe"); 515 int handle = mSecureElement.doOpenSecureElementConnection(); 516 if (handle == 0) { 517 Log.w(TAG, "Could not open the secure element"); 518 if (tempEnable) { 519 disableInternal(); 520 } 521 return; 522 } 523 524 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 525 526 for (byte[] cmd : apdus) { 527 byte[] resp = mSecureElement.doTransceive(handle, cmd); 528 if (resp == null) { 529 Log.w(TAG, "Transceive failed, could not wipe NFC-EE"); 530 break; 531 } 532 } 533 534 mDeviceHost.resetTimeouts(); 535 mSecureElement.doDisconnect(handle); 536 537 if (tempEnable) { 538 disableInternal(); 539 } 540 } 541 542 void updateState(int newState) { 543 synchronized (this) { 544 if (newState == mState) { 545 return; 546 } 547 mState = newState; 548 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 549 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 550 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 551 mContext.sendBroadcast(intent); 552 } 553 } 554 } 555 556 void saveNfcOnSetting(boolean on) { 557 synchronized (NfcService.this) { 558 mPrefsEditor.putBoolean(PREF_NFC_ON, on); 559 mPrefsEditor.apply(); 560 } 561 } 562 563 void playSound(int sound) { 564 synchronized (this) { 565 mSoundPool.play(sound, 1.0f, 1.0f, 0, 0, 1.0f); 566 } 567 } 568 569 @Override 570 public void onTerminate() { 571 super.onTerminate(); 572 // NFC application is persistent, it should not be destroyed by framework 573 Log.wtf(TAG, "NFC service is under attack!"); 574 } 575 576 final class NfcAdapterService extends INfcAdapter.Stub { 577 @Override 578 public boolean enable() throws RemoteException { 579 NfcService.enforceAdminPerm(mContext); 580 581 saveNfcOnSetting(true); 582 if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) { 583 Log.i(TAG, "denying enable() request (airplane mode)"); 584 return false; 585 } 586 new EnableDisableTask().execute(TASK_ENABLE); 587 588 return true; 589 } 590 591 @Override 592 public boolean disable() throws RemoteException { 593 NfcService.enforceAdminPerm(mContext); 594 595 saveNfcOnSetting(false); 596 new EnableDisableTask().execute(TASK_DISABLE); 597 598 return true; 599 } 600 601 @Override 602 public boolean isNdefPushEnabled() throws RemoteException { 603 synchronized (NfcService.this) { 604 return mIsNdefPushEnabled; 605 } 606 } 607 608 @Override 609 public boolean enableNdefPush() throws RemoteException { 610 NfcService.enforceAdminPerm(mContext); 611 synchronized(NfcService.this) { 612 if (mIsNdefPushEnabled) { 613 return true; 614 } 615 Log.i(TAG, "enabling NDEF Push"); 616 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 617 mPrefsEditor.apply(); 618 mIsNdefPushEnabled = true; 619 if (isNfcEnabled()) { 620 mP2pLinkManager.enableDisable(true, true); 621 } 622 } 623 return true; 624 } 625 626 @Override 627 public boolean disableNdefPush() throws RemoteException { 628 NfcService.enforceAdminPerm(mContext); 629 synchronized(NfcService.this) { 630 if (!mIsNdefPushEnabled) { 631 return true; 632 } 633 Log.i(TAG, "disabling NDEF Push"); 634 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 635 mPrefsEditor.apply(); 636 mIsNdefPushEnabled = false; 637 if (isNfcEnabled()) { 638 mP2pLinkManager.enableDisable(false, true); 639 } 640 } 641 return true; 642 } 643 644 @Override 645 public void setForegroundDispatch(PendingIntent intent, 646 IntentFilter[] filters, TechListParcel techListsParcel) { 647 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 648 649 // Short-cut the disable path 650 if (intent == null && filters == null && techListsParcel == null) { 651 mNfcDispatcher.setForegroundDispatch(null, null, null); 652 return; 653 } 654 655 // Validate the IntentFilters 656 if (filters != null) { 657 if (filters.length == 0) { 658 filters = null; 659 } else { 660 for (IntentFilter filter : filters) { 661 if (filter == null) { 662 throw new IllegalArgumentException("null IntentFilter"); 663 } 664 } 665 } 666 } 667 668 // Validate the tech lists 669 String[][] techLists = null; 670 if (techListsParcel != null) { 671 techLists = techListsParcel.getTechLists(); 672 } 673 674 mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 675 } 676 677 @Override 678 public void setForegroundNdefPush(NdefMessage msg, INdefPushCallback callback) { 679 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 680 mP2pLinkManager.setNdefToSend(msg, callback); 681 } 682 683 @Override 684 public INfcTag getNfcTagInterface() throws RemoteException { 685 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 686 return mNfcTagService; 687 } 688 689 @Override 690 public INfcAdapterExtras getNfcAdapterExtrasInterface() { 691 NfcService.enforceNfceeAdminPerm(mContext); 692 return mExtrasService; 693 } 694 695 @Override 696 public int getState() throws RemoteException { 697 synchronized (NfcService.this) { 698 return mState; 699 } 700 } 701 702 @Override 703 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 704 NfcService.this.dump(fd, pw, args); 705 } 706 }; 707 708 final class TagService extends INfcTag.Stub { 709 @Override 710 public int close(int nativeHandle) throws RemoteException { 711 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 712 713 TagEndpoint tag = null; 714 715 if (!isNfcEnabled()) { 716 return ErrorCodes.ERROR_NOT_INITIALIZED; 717 } 718 719 /* find the tag in the hmap */ 720 tag = (TagEndpoint) findObject(nativeHandle); 721 if (tag != null) { 722 /* Remove the device from the hmap */ 723 unregisterObject(nativeHandle); 724 tag.disconnect(); 725 return ErrorCodes.SUCCESS; 726 } 727 /* Restart polling loop for notification */ 728 applyRouting(); 729 return ErrorCodes.ERROR_DISCONNECT; 730 } 731 732 @Override 733 public int connect(int nativeHandle, int technology) throws RemoteException { 734 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 735 736 TagEndpoint tag = null; 737 738 if (!isNfcEnabled()) { 739 return ErrorCodes.ERROR_NOT_INITIALIZED; 740 } 741 742 /* find the tag in the hmap */ 743 tag = (TagEndpoint) findObject(nativeHandle); 744 if (tag == null) { 745 return ErrorCodes.ERROR_DISCONNECT; 746 } 747 748 if (technology == TagTechnology.NFC_B) { 749 return ErrorCodes.ERROR_NOT_SUPPORTED; 750 } 751 752 // Note that on most tags, all technologies are behind a single 753 // handle. This means that the connect at the lower levels 754 // will do nothing, as the tag is already connected to that handle. 755 if (tag.connect(technology)) { 756 return ErrorCodes.SUCCESS; 757 } else { 758 return ErrorCodes.ERROR_DISCONNECT; 759 } 760 } 761 762 @Override 763 public int reconnect(int nativeHandle) throws RemoteException { 764 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 765 766 TagEndpoint tag = null; 767 768 // Check if NFC is enabled 769 if (!isNfcEnabled()) { 770 return ErrorCodes.ERROR_NOT_INITIALIZED; 771 } 772 773 /* find the tag in the hmap */ 774 tag = (TagEndpoint) findObject(nativeHandle); 775 if (tag != null) { 776 if (tag.reconnect()) { 777 return ErrorCodes.SUCCESS; 778 } else { 779 return ErrorCodes.ERROR_DISCONNECT; 780 } 781 } 782 return ErrorCodes.ERROR_DISCONNECT; 783 } 784 785 @Override 786 public int[] getTechList(int nativeHandle) throws RemoteException { 787 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 788 789 // Check if NFC is enabled 790 if (!isNfcEnabled()) { 791 return null; 792 } 793 794 /* find the tag in the hmap */ 795 TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 796 if (tag != null) { 797 return tag.getTechList(); 798 } 799 return null; 800 } 801 802 @Override 803 public byte[] getUid(int nativeHandle) throws RemoteException { 804 TagEndpoint tag = null; 805 byte[] uid; 806 807 // Check if NFC is enabled 808 if (!isNfcEnabled()) { 809 return null; 810 } 811 812 /* find the tag in the hmap */ 813 tag = (TagEndpoint) findObject(nativeHandle); 814 if (tag != null) { 815 uid = tag.getUid(); 816 return uid; 817 } 818 return null; 819 } 820 821 @Override 822 public boolean isPresent(int nativeHandle) throws RemoteException { 823 TagEndpoint tag = null; 824 825 // Check if NFC is enabled 826 if (!isNfcEnabled()) { 827 return false; 828 } 829 830 /* find the tag in the hmap */ 831 tag = (TagEndpoint) findObject(nativeHandle); 832 if (tag == null) { 833 return false; 834 } 835 836 return tag.isPresent(); 837 } 838 839 @Override 840 public boolean isNdef(int nativeHandle) throws RemoteException { 841 TagEndpoint tag = null; 842 843 // Check if NFC is enabled 844 if (!isNfcEnabled()) { 845 return false; 846 } 847 848 /* find the tag in the hmap */ 849 tag = (TagEndpoint) findObject(nativeHandle); 850 int[] ndefInfo = new int[2]; 851 if (tag == null) { 852 return false; 853 } 854 return tag.checkNdef(ndefInfo); 855 } 856 857 @Override 858 public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 859 throws RemoteException { 860 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 861 862 TagEndpoint tag = null; 863 byte[] response; 864 865 // Check if NFC is enabled 866 if (!isNfcEnabled()) { 867 return null; 868 } 869 870 /* find the tag in the hmap */ 871 tag = (TagEndpoint) findObject(nativeHandle); 872 if (tag != null) { 873 // Check if length is within limits 874 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 875 return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 876 } 877 int[] targetLost = new int[1]; 878 response = tag.transceive(data, raw, targetLost); 879 int result; 880 if (response != null) { 881 result = TransceiveResult.RESULT_SUCCESS; 882 } else if (targetLost[0] == 1) { 883 result = TransceiveResult.RESULT_TAGLOST; 884 } else { 885 result = TransceiveResult.RESULT_FAILURE; 886 } 887 return new TransceiveResult(result, response); 888 } 889 return null; 890 } 891 892 @Override 893 public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 894 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 895 896 TagEndpoint tag; 897 898 // Check if NFC is enabled 899 if (!isNfcEnabled()) { 900 return null; 901 } 902 903 /* find the tag in the hmap */ 904 tag = (TagEndpoint) findObject(nativeHandle); 905 if (tag != null) { 906 byte[] buf = tag.readNdef(); 907 if (buf == null) { 908 return null; 909 } 910 911 /* Create an NdefMessage */ 912 try { 913 return new NdefMessage(buf); 914 } catch (FormatException e) { 915 return null; 916 } 917 } 918 return null; 919 } 920 921 @Override 922 public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 923 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 924 925 TagEndpoint tag; 926 927 // Check if NFC is enabled 928 if (!isNfcEnabled()) { 929 return ErrorCodes.ERROR_NOT_INITIALIZED; 930 } 931 932 /* find the tag in the hmap */ 933 tag = (TagEndpoint) findObject(nativeHandle); 934 if (tag == null) { 935 return ErrorCodes.ERROR_IO; 936 } 937 938 if (tag.writeNdef(msg.toByteArray())) { 939 return ErrorCodes.SUCCESS; 940 } else { 941 return ErrorCodes.ERROR_IO; 942 } 943 944 } 945 946 @Override 947 public int getLastError(int nativeHandle) throws RemoteException { 948 return(mDeviceHost.doGetLastError()); 949 } 950 951 @Override 952 public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 953 throw new UnsupportedOperationException(); 954 } 955 956 @Override 957 public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 958 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 959 960 TagEndpoint tag; 961 962 // Check if NFC is enabled 963 if (!isNfcEnabled()) { 964 return ErrorCodes.ERROR_NOT_INITIALIZED; 965 } 966 967 /* find the tag in the hmap */ 968 tag = (TagEndpoint) findObject(nativeHandle); 969 if (tag == null) { 970 return ErrorCodes.ERROR_IO; 971 } 972 973 if (tag.makeReadOnly()) { 974 return ErrorCodes.SUCCESS; 975 } else { 976 return ErrorCodes.ERROR_IO; 977 } 978 } 979 980 @Override 981 public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 982 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 983 984 TagEndpoint tag; 985 986 // Check if NFC is enabled 987 if (!isNfcEnabled()) { 988 return ErrorCodes.ERROR_NOT_INITIALIZED; 989 } 990 991 /* find the tag in the hmap */ 992 tag = (TagEndpoint) findObject(nativeHandle); 993 if (tag == null) { 994 return ErrorCodes.ERROR_IO; 995 } 996 997 if (tag.formatNdef(key)) { 998 return ErrorCodes.SUCCESS; 999 } else { 1000 return ErrorCodes.ERROR_IO; 1001 } 1002 } 1003 1004 @Override 1005 public Tag rediscover(int nativeHandle) throws RemoteException { 1006 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1007 1008 TagEndpoint tag = null; 1009 1010 // Check if NFC is enabled 1011 if (!isNfcEnabled()) { 1012 return null; 1013 } 1014 1015 /* find the tag in the hmap */ 1016 tag = (TagEndpoint) findObject(nativeHandle); 1017 if (tag != null) { 1018 // For now the prime usecase for rediscover() is to be able 1019 // to access the NDEF technology after formatting without 1020 // having to remove the tag from the field, or similar 1021 // to have access to NdefFormatable in case low-level commands 1022 // were used to remove NDEF. So instead of doing a full stack 1023 // rediscover (which is poorly supported at the moment anyway), 1024 // we simply remove these two technologies and detect them 1025 // again. 1026 tag.removeTechnology(TagTechnology.NDEF); 1027 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1028 NdefMessage[] msgs = tag.findAndReadNdef(); 1029 // Build a new Tag object to return 1030 Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 1031 tag.getTechExtras(), tag.getHandle(), this); 1032 return newTag; 1033 } 1034 return null; 1035 } 1036 1037 @Override 1038 public int setTimeout(int tech, int timeout) throws RemoteException { 1039 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1040 boolean success = mDeviceHost.setTimeout(tech, timeout); 1041 if (success) { 1042 return ErrorCodes.SUCCESS; 1043 } else { 1044 return ErrorCodes.ERROR_INVALID_PARAM; 1045 } 1046 } 1047 1048 @Override 1049 public int getTimeout(int tech) throws RemoteException { 1050 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1051 1052 return mDeviceHost.getTimeout(tech); 1053 } 1054 1055 @Override 1056 public void resetTimeouts() throws RemoteException { 1057 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1058 1059 mDeviceHost.resetTimeouts(); 1060 } 1061 1062 @Override 1063 public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1064 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1065 1066 return mDeviceHost.canMakeReadOnly(ndefType); 1067 } 1068 1069 @Override 1070 public int getMaxTransceiveLength(int tech) throws RemoteException { 1071 mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR); 1072 1073 return mDeviceHost.getMaxTransceiveLength(tech); 1074 } 1075 }; 1076 1077 private void _nfcEeClose(boolean checkPid, int callingPid) throws IOException { 1078 // Blocks until a pending open() or transceive() times out. 1079 //TODO: This is incorrect behavior - the close should interrupt pending 1080 // operations. However this is not supported by current hardware. 1081 1082 synchronized(NfcService.this) { 1083 if (!isNfcEnabled()) { 1084 throw new IOException("NFC adapter is disabled"); 1085 } 1086 if (mOpenEe == null) { 1087 throw new IOException("NFC EE closed"); 1088 } 1089 if (checkPid && mOpenEe.pid != -1 && callingPid != mOpenEe.pid) { 1090 throw new SecurityException("Wrong PID"); 1091 } 1092 1093 mDeviceHost.resetTimeouts(); 1094 mSecureElement.doDisconnect(mOpenEe.handle); 1095 mOpenEe = null; 1096 1097 applyRouting(); 1098 } 1099 } 1100 1101 final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub { 1102 private Bundle writeNoException() { 1103 Bundle p = new Bundle(); 1104 p.putInt("e", 0); 1105 return p; 1106 } 1107 private Bundle writeIoException(IOException e) { 1108 Bundle p = new Bundle(); 1109 p.putInt("e", -1); 1110 p.putString("m", e.getMessage()); 1111 return p; 1112 } 1113 1114 @Override 1115 public Bundle open(IBinder b) throws RemoteException { 1116 NfcService.enforceNfceeAdminPerm(mContext); 1117 1118 Bundle result; 1119 try { 1120 _open(b); 1121 result = writeNoException(); 1122 } catch (IOException e) { 1123 result = writeIoException(e); 1124 } 1125 return result; 1126 } 1127 1128 private void _open(IBinder b) throws IOException, RemoteException { 1129 synchronized(NfcService.this) { 1130 if (!isNfcEnabled()) { 1131 throw new IOException("NFC adapter is disabled"); 1132 } 1133 if (mOpenEe != null) { 1134 throw new IOException("NFC EE already open"); 1135 } 1136 1137 int handle = mSecureElement.doOpenSecureElementConnection(); 1138 if (handle == 0) { 1139 throw new IOException("NFC EE failed to open"); 1140 } 1141 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000); 1142 1143 mOpenEe = new OpenSecureElement(getCallingPid(), handle); 1144 try { 1145 b.linkToDeath(mOpenEe, 0); 1146 } catch (RemoteException e) { 1147 mOpenEe.binderDied(); 1148 } 1149 1150 // Add the calling package to the list of packages that have accessed 1151 // the secure element. 1152 for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) { 1153 mSePackages.add(packageName); 1154 } 1155 } 1156 } 1157 1158 @Override 1159 public Bundle close() throws RemoteException { 1160 NfcService.enforceNfceeAdminPerm(mContext); 1161 1162 Bundle result; 1163 try { 1164 _nfcEeClose(true, getCallingPid()); 1165 result = writeNoException(); 1166 } catch (IOException e) { 1167 result = writeIoException(e); 1168 } 1169 return result; 1170 } 1171 1172 @Override 1173 public Bundle transceive(byte[] in) throws RemoteException { 1174 NfcService.enforceNfceeAdminPerm(mContext); 1175 1176 Bundle result; 1177 byte[] out; 1178 try { 1179 out = _transceive(in); 1180 result = writeNoException(); 1181 result.putByteArray("out", out); 1182 } catch (IOException e) { 1183 result = writeIoException(e); 1184 } 1185 return result; 1186 } 1187 1188 private byte[] _transceive(byte[] data) throws IOException, RemoteException { 1189 synchronized(NfcService.this) { 1190 if (!isNfcEnabled()) { 1191 throw new IOException("NFC is not enabled"); 1192 } 1193 if (mOpenEe == null){ 1194 throw new IOException("NFC EE is not open"); 1195 } 1196 if (getCallingPid() != mOpenEe.pid) { 1197 throw new SecurityException("Wrong PID"); 1198 } 1199 } 1200 1201 return mSecureElement.doTransceive(mOpenEe.handle, data); 1202 } 1203 1204 @Override 1205 public int getCardEmulationRoute() throws RemoteException { 1206 NfcService.enforceNfceeAdminPerm(mContext); 1207 return mEeRoutingState; 1208 } 1209 1210 @Override 1211 public void setCardEmulationRoute(int route) throws RemoteException { 1212 NfcService.enforceNfceeAdminPerm(mContext); 1213 mEeRoutingState = route; 1214 applyRouting(); 1215 } 1216 1217 @Override 1218 public void authenticate(byte[] token) throws RemoteException { 1219 NfcService.enforceNfceeAdminPerm(mContext); 1220 } 1221 }; 1222 1223 /** resources kept while secure element is open */ 1224 private class OpenSecureElement implements IBinder.DeathRecipient { 1225 public int pid; // pid that opened SE 1226 public int handle; // low-level handle 1227 public OpenSecureElement(int pid, int handle) { 1228 this.pid = pid; 1229 this.handle = handle; 1230 } 1231 @Override 1232 public void binderDied() { 1233 synchronized (NfcService.this) { 1234 if (DBG) Log.d(TAG, "Tracked app " + pid + " died"); 1235 pid = -1; 1236 try { 1237 _nfcEeClose(false, -1); 1238 } catch (IOException e) { /* already closed */ } 1239 } 1240 } 1241 } 1242 1243 boolean isNfcEnabled() { 1244 synchronized (this) { 1245 return mState == NfcAdapter.STATE_ON; 1246 } 1247 } 1248 1249 class WatchDogThread extends Thread { 1250 boolean mWatchDogCanceled = false; 1251 @Override 1252 public void run() { 1253 boolean slept = false; 1254 while (!slept) { 1255 try { 1256 Thread.sleep(10000); 1257 slept = true; 1258 } catch (InterruptedException e) { } 1259 } 1260 synchronized (this) { 1261 if (!mWatchDogCanceled) { 1262 // Trigger watch-dog 1263 Log.e(TAG, "Watch dog triggered"); 1264 mDeviceHost.doAbort(); 1265 } 1266 } 1267 } 1268 public synchronized void cancel() { 1269 mWatchDogCanceled = true; 1270 } 1271 } 1272 1273 /** apply NFC discovery and EE routing */ 1274 void applyRouting() { 1275 synchronized (this) { 1276 if (!isNfcEnabled() || mOpenEe != null) { 1277 return; 1278 } 1279 if (mIsScreenUnlocked) { 1280 if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) { 1281 Log.d(TAG, "NFC-EE routing ON"); 1282 mDeviceHost.doSelectSecureElement(); 1283 } else { 1284 Log.d(TAG, "NFC-EE routing OFF"); 1285 mDeviceHost.doDeselectSecureElement(); 1286 } 1287 Log.d(TAG, "NFC-C polling ON"); 1288 mDeviceHost.enableDiscovery(); 1289 } else { 1290 Log.d(TAG, "NFC-EE routing OFF"); 1291 mDeviceHost.doDeselectSecureElement(); 1292 Log.d(TAG, "NFC-C polling OFF"); 1293 mDeviceHost.disableDiscovery(); 1294 } 1295 } 1296 } 1297 1298 /** Disconnect any target if present */ 1299 void maybeDisconnectTarget() { 1300 if (!isNfcEnabled()) { 1301 return; 1302 } 1303 Object[] objectsToDisconnect; 1304 synchronized (this) { 1305 Object[] objectValues = mObjectMap.values().toArray(); 1306 // Copy the array before we clear mObjectMap, 1307 // just in case the HashMap values are backed by the same array 1308 objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 1309 mObjectMap.clear(); 1310 } 1311 for (Object o : objectsToDisconnect) { 1312 if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 1313 if (o instanceof TagEndpoint) { 1314 // Disconnect from tags 1315 TagEndpoint tag = (TagEndpoint) o; 1316 tag.disconnect(); 1317 } else if (o instanceof NfcDepEndpoint) { 1318 // Disconnect from P2P devices 1319 NfcDepEndpoint device = (NfcDepEndpoint) o; 1320 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1321 // Remote peer is target, request disconnection 1322 device.disconnect(); 1323 } else { 1324 // Remote peer is initiator, we cannot disconnect 1325 // Just wait for field removal 1326 } 1327 } 1328 } 1329 } 1330 1331 Object findObject(int key) { 1332 synchronized (this) { 1333 Object device = mObjectMap.get(key); 1334 if (device == null) { 1335 Log.w(TAG, "Handle not found"); 1336 } 1337 return device; 1338 } 1339 } 1340 1341 void registerTagObject(TagEndpoint tag) { 1342 synchronized (this) { 1343 mObjectMap.put(tag.getHandle(), tag); 1344 } 1345 } 1346 1347 void unregisterObject(int handle) { 1348 synchronized (this) { 1349 mObjectMap.remove(handle); 1350 } 1351 } 1352 1353 /** For use by code in this process */ 1354 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1355 throws IOException, LlcpException { 1356 return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1357 } 1358 1359 /** For use by code in this process */ 1360 public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1361 int linearBufferLength) throws IOException, LlcpException { 1362 return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1363 } 1364 1365 public void sendMockNdefTag(NdefMessage msg) { 1366 sendMessage(MSG_MOCK_NDEF, msg); 1367 } 1368 1369 void sendMessage(int what, Object obj) { 1370 Message msg = mHandler.obtainMessage(); 1371 msg.what = what; 1372 msg.obj = obj; 1373 mHandler.sendMessage(msg); 1374 } 1375 1376 final class NfcServiceHandler extends Handler { 1377 @Override 1378 public void handleMessage(Message msg) { 1379 switch (msg.what) { 1380 case MSG_MOCK_NDEF: { 1381 NdefMessage ndefMsg = (NdefMessage) msg.obj; 1382 Bundle extras = new Bundle(); 1383 extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 1384 extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 1385 extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 1386 extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 1387 Tag tag = Tag.createMockTag(new byte[] { 0x00 }, 1388 new int[] { TagTechnology.NDEF }, 1389 new Bundle[] { extras }); 1390 Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 1391 Log.d(TAG, tag.toString()); 1392 boolean delivered = mNfcDispatcher.dispatchTag(tag, 1393 new NdefMessage[] { ndefMsg }); 1394 if (delivered) { 1395 playSound(mEndSound); 1396 } else { 1397 playSound(mErrorSound); 1398 } 1399 break; 1400 } 1401 1402 case MSG_NDEF_TAG: 1403 if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 1404 TagEndpoint tag = (TagEndpoint) msg.obj; 1405 playSound(mStartSound); 1406 NdefMessage[] ndefMsgs = tag.findAndReadNdef(); 1407 1408 if (ndefMsgs != null) { 1409 tag.startPresenceChecking(); 1410 dispatchTagEndpoint(tag, ndefMsgs); 1411 } else { 1412 if (tag.reconnect()) { 1413 tag.startPresenceChecking(); 1414 dispatchTagEndpoint(tag, null); 1415 } else { 1416 tag.disconnect(); 1417 playSound(mErrorSound); 1418 } 1419 } 1420 break; 1421 1422 case MSG_CARD_EMULATION: 1423 if (DBG) Log.d(TAG, "Card Emulation message"); 1424 byte[] aid = (byte[]) msg.obj; 1425 /* Send broadcast */ 1426 Intent aidIntent = new Intent(); 1427 aidIntent.setAction(ACTION_AID_SELECTED); 1428 aidIntent.putExtra(EXTRA_AID, aid); 1429 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED); 1430 sendSeBroadcast(aidIntent); 1431 break; 1432 1433 case MSG_SE_EMV_CARD_REMOVAL: 1434 if (DBG) Log.d(TAG, "Card Removal message"); 1435 /* Send broadcast */ 1436 Intent cardRemovalIntent = new Intent(); 1437 cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL); 1438 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL); 1439 sendSeBroadcast(cardRemovalIntent); 1440 break; 1441 1442 case MSG_SE_APDU_RECEIVED: 1443 if (DBG) Log.d(TAG, "APDU Received message"); 1444 byte[] apduBytes = (byte[]) msg.obj; 1445 /* Send broadcast */ 1446 Intent apduReceivedIntent = new Intent(); 1447 apduReceivedIntent.setAction(ACTION_APDU_RECEIVED); 1448 if (apduBytes != null && apduBytes.length > 0) { 1449 apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes); 1450 } 1451 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED); 1452 sendSeBroadcast(apduReceivedIntent); 1453 break; 1454 1455 case MSG_SE_MIFARE_ACCESS: 1456 if (DBG) Log.d(TAG, "MIFARE access message"); 1457 /* Send broadcast */ 1458 byte[] mifareCmd = (byte[]) msg.obj; 1459 Intent mifareAccessIntent = new Intent(); 1460 mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED); 1461 if (mifareCmd != null && mifareCmd.length > 1) { 1462 int mifareBlock = mifareCmd[1] & 0xff; 1463 if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock); 1464 mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock); 1465 } 1466 if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED); 1467 sendSeBroadcast(mifareAccessIntent); 1468 break; 1469 1470 case MSG_LLCP_LINK_ACTIVATION: 1471 llcpActivated((NfcDepEndpoint) msg.obj); 1472 break; 1473 1474 case MSG_LLCP_LINK_DEACTIVATED: 1475 NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 1476 boolean needsDisconnect = false; 1477 1478 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 1479 synchronized (NfcService.this) { 1480 /* Check if the device has been already unregistered */ 1481 if (mObjectMap.remove(device.getHandle()) != null) { 1482 /* Disconnect if we are initiator */ 1483 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1484 if (DBG) Log.d(TAG, "disconnecting from target"); 1485 needsDisconnect = true; 1486 } else { 1487 if (DBG) Log.d(TAG, "not disconnecting from initiator"); 1488 } 1489 } 1490 } 1491 if (needsDisconnect) { 1492 device.disconnect(); // restarts polling loop 1493 } 1494 1495 mP2pLinkManager.onLlcpDeactivated(); 1496 break; 1497 1498 case MSG_TARGET_DESELECTED: 1499 /* Broadcast Intent Target Deselected */ 1500 if (DBG) Log.d(TAG, "Target Deselected"); 1501 Intent intent = new Intent(); 1502 intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION); 1503 if (DBG) Log.d(TAG, "Broadcasting Intent"); 1504 mContext.sendOrderedBroadcast(intent, NFC_PERM); 1505 break; 1506 1507 case MSG_SE_FIELD_ACTIVATED: { 1508 if (DBG) Log.d(TAG, "SE FIELD ACTIVATED"); 1509 Intent eventFieldOnIntent = new Intent(); 1510 eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED); 1511 sendSeBroadcast(eventFieldOnIntent); 1512 break; 1513 } 1514 1515 case MSG_SE_FIELD_DEACTIVATED: { 1516 if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED"); 1517 Intent eventFieldOffIntent = new Intent(); 1518 eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED); 1519 sendSeBroadcast(eventFieldOffIntent); 1520 break; 1521 } 1522 1523 default: 1524 Log.e(TAG, "Unknown message received"); 1525 break; 1526 } 1527 } 1528 1529 private void sendSeBroadcast(Intent intent) { 1530 mNfcDispatcher.resumeAppSwitches(); 1531 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 1532 mContext.sendBroadcast(intent, NFCEE_ADMIN_PERM); 1533 } 1534 1535 private boolean llcpActivated(NfcDepEndpoint device) { 1536 Log.d(TAG, "LLCP Activation message"); 1537 1538 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1539 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1540 if (device.connect()) { 1541 /* Check LLCP compliancy */ 1542 if (mDeviceHost.doCheckLlcp()) { 1543 /* Activate LLCP Link */ 1544 if (mDeviceHost.doActivateLlcp()) { 1545 if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 1546 boolean isZeroClickOn; 1547 synchronized (NfcService.this) { 1548 // Register P2P device 1549 mObjectMap.put(device.getHandle(), device); 1550 } 1551 mP2pLinkManager.onLlcpActivated(); 1552 return true; 1553 } else { 1554 /* should not happen */ 1555 Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1556 device.disconnect(); 1557 } 1558 } else { 1559 if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1560 device.disconnect(); 1561 } 1562 } else { 1563 if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1564 /* 1565 * The polling loop should have been restarted in failing 1566 * doConnect 1567 */ 1568 } 1569 } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1570 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1571 /* Check LLCP compliancy */ 1572 if (mDeviceHost.doCheckLlcp()) { 1573 /* Activate LLCP Link */ 1574 if (mDeviceHost.doActivateLlcp()) { 1575 if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 1576 boolean isZeroClickOn; 1577 synchronized (NfcService.this) { 1578 // Register P2P device 1579 mObjectMap.put(device.getHandle(), device); 1580 } 1581 mP2pLinkManager.onLlcpActivated(); 1582 return true; 1583 } 1584 } else { 1585 Log.w(TAG, "checkLlcp failed"); 1586 } 1587 } 1588 1589 return false; 1590 } 1591 1592 private void dispatchTagEndpoint(TagEndpoint tagEndpoint, NdefMessage[] msgs) { 1593 Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1594 tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1595 registerTagObject(tagEndpoint); 1596 if (!mNfcDispatcher.dispatchTag(tag, msgs)) { 1597 unregisterObject(tagEndpoint.getHandle()); 1598 playSound(mErrorSound); 1599 } else { 1600 playSound(mEndSound); 1601 } 1602 } 1603 } 1604 1605 private NfcServiceHandler mHandler = new NfcServiceHandler(); 1606 1607 class EnableDisableDiscoveryTask extends AsyncTask<Boolean, Void, Void> { 1608 @Override 1609 protected Void doInBackground(Boolean... params) { 1610 if (DBG) Log.d(TAG, "EnableDisableDiscoveryTask: enable = " + params[0]); 1611 1612 if (params != null && params.length > 0 && params[0]) { 1613 synchronized (NfcService.this) { 1614 if (!mIsScreenUnlocked) { 1615 mIsScreenUnlocked = true; 1616 applyRouting(); 1617 } else { 1618 if (DBG) Log.d(TAG, "Ignoring enable request"); 1619 } 1620 } 1621 } else { 1622 mWakeLock.acquire(); 1623 synchronized (NfcService.this) { 1624 if (mIsScreenUnlocked) { 1625 mIsScreenUnlocked = false; 1626 // applyRouting(); 1627 /* 1628 * TODO undo this after the LLCP stack is fixed. 1629 * This is done locally here since the LLCP stack is still using 1630 * globals without holding any locks, and if we attempt to change 1631 * the NFCEE routing while the target is still connected (and it's 1632 * a P2P target) the async LLCP callbacks will crash since the routing 1633 * manipulation code is overwriting globals it relies on. This hack should 1634 * be removed when the LLCP stack is fixed. 1635 */ 1636 if (isNfcEnabled() && mOpenEe == null) { 1637 Log.d(TAG, "NFC-C polling OFF"); 1638 mDeviceHost.disableDiscovery(); 1639 maybeDisconnectTarget(); 1640 Log.d(TAG, "NFC-EE routing OFF"); 1641 mDeviceHost.doDeselectSecureElement(); 1642 } 1643 } else { 1644 if (DBG) Log.d(TAG, "Ignoring disable request"); 1645 } 1646 } 1647 mWakeLock.release(); 1648 } 1649 return null; 1650 } 1651 } 1652 1653 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1654 @Override 1655 public void onReceive(Context context, Intent intent) { 1656 String action = intent.getAction(); 1657 if (action.equals( 1658 NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { 1659 if (DBG) Log.d(TAG, "INERNAL_TARGET_DESELECTED_ACTION"); 1660 1661 /* Restart polling loop for notification */ 1662 applyRouting(); 1663 1664 } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1665 // Only enable if the screen is unlocked. If the screen is locked 1666 // Intent.ACTION_USER_PRESENT will be broadcast when the screen is 1667 // unlocked. 1668 boolean enable = !mKeyguard.isKeyguardLocked(); 1669 1670 // Perform discovery enable in thread to protect against ANR when the 1671 // NFC stack wedges. This is *not* the correct way to fix this issue - 1672 // configuration of the local NFC adapter should be very quick and should 1673 // be safe on the main thread, and the NFC stack should not wedge. 1674 new EnableDisableDiscoveryTask().execute(enable); 1675 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1676 // Perform discovery disable in thread to protect against ANR when the 1677 // NFC stack wedges. This is *not* the correct way to fix this issue - 1678 // configuration of the local NFC adapter should be very quick and should 1679 // be safe on the main thread, and the NFC stack should not wedge. 1680 new EnableDisableDiscoveryTask().execute(Boolean.FALSE); 1681 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1682 // The user has unlocked the screen. Enabled! 1683 new EnableDisableDiscoveryTask().execute(Boolean.TRUE); 1684 } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) { 1685 EnableDisableTask eeWipeTask = new EnableDisableTask(); 1686 eeWipeTask.execute(TASK_EE_WIPE); 1687 try { 1688 eeWipeTask.get(); // blocks until EE wipe is complete 1689 } catch (ExecutionException e) { 1690 Log.w(TAG, "failed to wipe NFC-EE"); 1691 } catch (InterruptedException e) { 1692 Log.w(TAG, "failed to wipe NFC-EE"); 1693 } 1694 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { 1695 boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false); 1696 if (dataRemoved) { 1697 Uri data = intent.getData(); 1698 if (data == null) return; 1699 String packageName = data.getSchemeSpecificPart(); 1700 1701 synchronized (NfcService.this) { 1702 if (mSePackages.contains(packageName)) { 1703 new EnableDisableTask().execute(TASK_EE_WIPE); 1704 mSePackages.remove(packageName); 1705 } 1706 } 1707 } 1708 } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 1709 boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 1710 // Query the airplane mode from Settings.System just to make sure that 1711 // some random app is not sending this intent 1712 if (isAirplaneModeOn != isAirplaneModeOn()) { 1713 return; 1714 } 1715 if (!mIsAirplaneSensitive) { 1716 return; 1717 } 1718 if (isAirplaneModeOn) { 1719 new EnableDisableTask().execute(TASK_DISABLE); 1720 } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 1721 new EnableDisableTask().execute(TASK_ENABLE); 1722 } 1723 } 1724 } 1725 }; 1726 1727 /** Returns true if airplane mode is currently on */ 1728 boolean isAirplaneModeOn() { 1729 return Settings.System.getInt(mContext.getContentResolver(), 1730 Settings.System.AIRPLANE_MODE_ON, 0) == 1; 1731 } 1732 1733 /** for debugging only - no il8n */ 1734 static String stateToString(int state) { 1735 switch (state) { 1736 case NfcAdapter.STATE_OFF: 1737 return "off"; 1738 case NfcAdapter.STATE_TURNING_ON: 1739 return "turning on"; 1740 case NfcAdapter.STATE_ON: 1741 return "on"; 1742 case NfcAdapter.STATE_TURNING_OFF: 1743 return "turning off"; 1744 default: 1745 return "<error>"; 1746 } 1747 } 1748 1749 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1750 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1751 != PackageManager.PERMISSION_GRANTED) { 1752 pw.println("Permission Denial: can't dump nfc from from pid=" 1753 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1754 + " without permission " + android.Manifest.permission.DUMP); 1755 return; 1756 } 1757 1758 synchronized (this) { 1759 pw.println("mState=" + stateToString(mState)); 1760 pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 1761 pw.println("mIsScreenUnlocked=" + mIsScreenUnlocked); 1762 pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 1763 pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 1764 mP2pLinkManager.dump(fd, pw, args); 1765 pw.println(mDeviceHost.dump()); 1766 } 1767 } 1768 } 1769