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