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