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