NfcService.java revision 34322b73c1e09907cb007e86bae77c744b338cd7
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.nfc; 18 19import android.app.ActivityManager; 20import android.app.Application; 21import android.app.KeyguardManager; 22import android.app.PendingIntent; 23import android.app.ActivityManager.RunningTaskInfo; 24import android.content.BroadcastReceiver; 25import android.content.ContentResolver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.content.SharedPreferences; 30import android.content.pm.PackageManager; 31import android.content.res.Resources.NotFoundException; 32import android.media.AudioManager; 33import android.media.SoundPool; 34import android.nfc.BeamShareData; 35import android.nfc.ErrorCodes; 36import android.nfc.FormatException; 37import android.nfc.IAppCallback; 38import android.nfc.INfcAdapter; 39import android.nfc.INfcAdapterExtras; 40import android.nfc.INfcCardEmulation; 41import android.nfc.INfcLockscreenDispatch; 42import android.nfc.INfcTag; 43import android.nfc.NdefMessage; 44import android.nfc.NfcAdapter; 45import android.nfc.Tag; 46import android.nfc.TechListParcel; 47import android.nfc.TransceiveResult; 48import android.nfc.tech.Ndef; 49import android.nfc.tech.TagTechnology; 50import android.os.AsyncTask; 51import android.os.Binder; 52import android.os.Build; 53import android.os.Bundle; 54import android.os.Handler; 55import android.os.IBinder; 56import android.os.Message; 57import android.os.PowerManager; 58import android.os.Process; 59import android.os.RemoteException; 60import android.os.ServiceManager; 61import android.os.UserHandle; 62import android.provider.Settings; 63import android.util.Log; 64 65import com.android.nfc.DeviceHost.DeviceHostListener; 66import com.android.nfc.DeviceHost.LlcpConnectionlessSocket; 67import com.android.nfc.DeviceHost.LlcpServerSocket; 68import com.android.nfc.DeviceHost.LlcpSocket; 69import com.android.nfc.DeviceHost.NfcDepEndpoint; 70import com.android.nfc.DeviceHost.TagEndpoint; 71import com.android.nfc.cardemulation.CardEmulationManager; 72import com.android.nfc.dhimpl.NativeNfcManager; 73import com.android.nfc.handover.HandoverManager; 74 75import java.io.FileDescriptor; 76import java.io.PrintWriter; 77import java.util.Arrays; 78import java.util.HashMap; 79import java.util.List; 80import java.util.Map; 81import java.util.NoSuchElementException; 82 83public class NfcService implements DeviceHostListener { 84 static final boolean DBG = false; 85 static final String TAG = "NfcService"; 86 87 public static final String SERVICE_NAME = "nfc"; 88 89 public static final String PREF = "NfcServicePrefs"; 90 91 static final String PREF_NFC_ON = "nfc_on"; 92 static final boolean NFC_ON_DEFAULT = true; 93 static final String PREF_NDEF_PUSH_ON = "ndef_push_on"; 94 static final boolean NDEF_PUSH_ON_DEFAULT = true; 95 static final String PREF_FIRST_BEAM = "first_beam"; 96 static final String PREF_FIRST_BOOT = "first_boot"; 97 static final String PREF_AIRPLANE_OVERRIDE = "airplane_override"; 98 99 static final int MSG_NDEF_TAG = 0; 100 static final int MSG_LLCP_LINK_ACTIVATION = 2; 101 static final int MSG_LLCP_LINK_DEACTIVATED = 3; 102 static final int MSG_MOCK_NDEF = 7; 103 static final int MSG_LLCP_LINK_FIRST_PACKET = 15; 104 static final int MSG_ROUTE_AID = 16; 105 static final int MSG_UNROUTE_AID = 17; 106 static final int MSG_COMMIT_ROUTING = 18; 107 static final int MSG_INVOKE_BEAM = 19; 108 109 static final int TASK_ENABLE = 1; 110 static final int TASK_DISABLE = 2; 111 static final int TASK_BOOT = 3; 112 113 // Polling technology masks 114 static final int NFC_POLL_A = 0x01; 115 static final int NFC_POLL_B = 0x02; 116 static final int NFC_POLL_F = 0x04; 117 static final int NFC_POLL_ISO15693 = 0x08; 118 static final int NFC_POLL_B_PRIME = 0x10; 119 static final int NFC_POLL_KOVIO = 0x20; 120 121 // minimum screen state that enables NFC polling 122 static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 123 124 // Time to wait for NFC controller to initialize before watchdog 125 // goes off. This time is chosen large, because firmware download 126 // may be a part of initialization. 127 static final int INIT_WATCHDOG_MS = 90000; 128 129 // Time to wait for routing to be applied before watchdog 130 // goes off 131 static final int ROUTING_WATCHDOG_MS = 10000; 132 133 // Default delay used for presence checks 134 static final int DEFAULT_PRESENCE_CHECK_DELAY = 125; 135 136 // The amount of time we wait before manually launching 137 // the Beam animation when called through the share menu. 138 static final int INVOKE_BEAM_DELAY_MS = 1000; 139 140 // for use with playSound() 141 public static final int SOUND_START = 0; 142 public static final int SOUND_END = 1; 143 public static final int SOUND_ERROR = 2; 144 145 public static final String ACTION_LLCP_UP = 146 "com.android.nfc.action.LLCP_UP"; 147 148 public static final String ACTION_LLCP_DOWN = 149 "com.android.nfc.action.LLCP_DOWN"; 150 151 // NFC Execution Environment 152 // fields below are protected by this 153 private final ReaderModeDeathRecipient mReaderModeDeathRecipient = 154 new ReaderModeDeathRecipient(); 155 156 private boolean mDiscoveryEnabled = false; 157 private int mLockscreenPollMask; 158 private boolean mLockscreenDispatchEnabled; 159 160 // fields below are used in multiple threads and protected by synchronized(this) 161 final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); 162 int mScreenState; 163 boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning 164 boolean mIsNdefPushEnabled; 165 NfcDiscoveryParameters mCurrentDiscoveryParameters; 166 167 ReaderModeParams mReaderModeParams; 168 169 // mState is protected by this, however it is only modified in onCreate() 170 // and the default AsyncTask thread so it is read unprotected from that 171 // thread 172 int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc 173 // fields below are final after onCreate() 174 Context mContext; 175 private DeviceHost mDeviceHost; 176 private SharedPreferences mPrefs; 177 private SharedPreferences.Editor mPrefsEditor; 178 private PowerManager.WakeLock mRoutingWakeLock; 179 180 int mStartSound; 181 int mEndSound; 182 int mErrorSound; 183 SoundPool mSoundPool; // playback synchronized on this 184 P2pLinkManager mP2pLinkManager; 185 TagService mNfcTagService; 186 NfcAdapterService mNfcAdapter; 187 boolean mIsAirplaneSensitive; 188 boolean mIsAirplaneToggleable; 189 boolean mIsDebugBuild; 190 boolean mIsHceCapable; 191 192 private NfcDispatcher mNfcDispatcher; 193 private PowerManager mPowerManager; 194 private KeyguardManager mKeyguard; 195 private HandoverManager mHandoverManager; 196 private ContentResolver mContentResolver; 197 private CardEmulationManager mCardEmulationManager; 198 199 private ScreenStateHelper mScreenStateHelper; 200 private ForegroundUtils mForegroundUtils; 201 202 private int mUserId; 203 private static NfcService sService; 204 205 public static NfcService getInstance() { 206 return sService; 207 } 208 209 @Override 210 public void onRemoteEndpointDiscovered(TagEndpoint tag) { 211 sendMessage(NfcService.MSG_NDEF_TAG, tag); 212 } 213 214 /** 215 * Notifies transaction 216 */ 217 @Override 218 public void onHostCardEmulationActivated() { 219 if (mCardEmulationManager != null) { 220 mCardEmulationManager.onHostCardEmulationActivated(); 221 } 222 } 223 224 @Override 225 public void onHostCardEmulationData(byte[] data) { 226 if (mCardEmulationManager != null) { 227 mCardEmulationManager.onHostCardEmulationData(data); 228 } 229 } 230 231 @Override 232 public void onHostCardEmulationDeactivated() { 233 if (mCardEmulationManager != null) { 234 mCardEmulationManager.onHostCardEmulationDeactivated(); 235 } 236 } 237 238 /** 239 * Notifies P2P Device detected, to activate LLCP link 240 */ 241 @Override 242 public void onLlcpLinkActivated(NfcDepEndpoint device) { 243 sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device); 244 } 245 246 /** 247 * Notifies P2P Device detected, to activate LLCP link 248 */ 249 @Override 250 public void onLlcpLinkDeactivated(NfcDepEndpoint device) { 251 sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device); 252 } 253 254 /** 255 * Notifies P2P Device detected, first packet received over LLCP link 256 */ 257 @Override 258 public void onLlcpFirstPacketReceived(NfcDepEndpoint device) { 259 sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device); 260 } 261 262 final class ReaderModeParams { 263 public int flags; 264 public IAppCallback callback; 265 public int presenceCheckDelay; 266 } 267 268 public NfcService(Application nfcApplication) { 269 mUserId = ActivityManager.getCurrentUser(); 270 mContext = nfcApplication; 271 272 mNfcTagService = new TagService(); 273 mNfcAdapter = new NfcAdapterService(); 274 Log.i(TAG, "Starting NFC service"); 275 276 sService = this; 277 278 mScreenStateHelper = new ScreenStateHelper(mContext); 279 mContentResolver = mContext.getContentResolver(); 280 mDeviceHost = new NativeNfcManager(mContext, this); 281 282 mHandoverManager = new HandoverManager(mContext); 283 boolean isNfcProvisioningEnabled = false; 284 try { 285 isNfcProvisioningEnabled = mContext.getResources().getBoolean( 286 R.bool.enable_nfc_provisioning); 287 } catch (NotFoundException e) { 288 } 289 290 if (isNfcProvisioningEnabled) { 291 mInProvisionMode = Settings.Secure.getInt(mContentResolver, 292 Settings.Global.DEVICE_PROVISIONED, 0) == 0; 293 } else { 294 mInProvisionMode = false; 295 } 296 297 mHandoverManager.setEnabled(!mInProvisionMode); 298 mNfcDispatcher = new NfcDispatcher(mContext, mHandoverManager, mInProvisionMode); 299 mP2pLinkManager = new P2pLinkManager(mContext, mHandoverManager, 300 mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize()); 301 302 mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 303 mPrefsEditor = mPrefs.edit(); 304 305 mState = NfcAdapter.STATE_OFF; 306 mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT); 307 308 mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE); 309 310 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 311 312 mRoutingWakeLock = mPowerManager.newWakeLock( 313 PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock"); 314 315 mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 316 mScreenState = mScreenStateHelper.checkScreenState(); 317 318 ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 319 320 // Intents for all users 321 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); 322 filter.addAction(Intent.ACTION_SCREEN_ON); 323 filter.addAction(Intent.ACTION_USER_PRESENT); 324 filter.addAction(Intent.ACTION_USER_SWITCHED); 325 registerForAirplaneMode(filter); 326 mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); 327 328 PackageManager pm = mContext.getPackageManager(); 329 mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION); 330 if (mIsHceCapable) { 331 mCardEmulationManager = new CardEmulationManager(mContext); 332 } 333 mForegroundUtils = ForegroundUtils.getInstance(); 334 new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks 335 } 336 337 void initSoundPool() { 338 synchronized (this) { 339 if (mSoundPool == null) { 340 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); 341 mStartSound = mSoundPool.load(mContext, R.raw.start, 1); 342 mEndSound = mSoundPool.load(mContext, R.raw.end, 1); 343 mErrorSound = mSoundPool.load(mContext, R.raw.error, 1); 344 } 345 } 346 } 347 348 void releaseSoundPool() { 349 synchronized (this) { 350 if (mSoundPool != null) { 351 mSoundPool.release(); 352 mSoundPool = null; 353 } 354 } 355 } 356 357 void registerForAirplaneMode(IntentFilter filter) { 358 final String airplaneModeRadios = Settings.System.getString(mContentResolver, 359 Settings.Global.AIRPLANE_MODE_RADIOS); 360 final String toggleableRadios = Settings.System.getString(mContentResolver, 361 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 362 363 mIsAirplaneSensitive = airplaneModeRadios == null ? true : 364 airplaneModeRadios.contains(Settings.Global.RADIO_NFC); 365 mIsAirplaneToggleable = toggleableRadios == null ? false : 366 toggleableRadios.contains(Settings.Global.RADIO_NFC); 367 368 if (mIsAirplaneSensitive) { 369 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 370 } 371 } 372 373 /** 374 * Manages tasks that involve turning on/off the NFC controller. 375 * <p/> 376 * <p>All work that might turn the NFC adapter on or off must be done 377 * through this task, to keep the handling of mState simple. 378 * In other words, mState is only modified in these tasks (and we 379 * don't need a lock to read it in these tasks). 380 * <p/> 381 * <p>These tasks are all done on the same AsyncTask background 382 * thread, so they are serialized. Each task may temporarily transition 383 * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in 384 * either STATE_ON or STATE_OFF. This way each task can be guaranteed 385 * of starting in either STATE_OFF or STATE_ON, without needing to hold 386 * NfcService.this for the entire task. 387 * <p/> 388 * <p>AsyncTask's are also implicitly queued. This is useful for corner 389 * cases like turning airplane mode on while TASK_ENABLE is in progress. 390 * The TASK_DISABLE triggered by airplane mode will be correctly executed 391 * immediately after TASK_ENABLE is complete. This seems like the most sane 392 * way to deal with these situations. 393 * <p/> 394 * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing 395 * preferences 396 * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing 397 * preferences 398 * <p>{@link #TASK_BOOT} does first boot work and may enable NFC 399 */ 400 class EnableDisableTask extends AsyncTask<Integer, Void, Void> { 401 @Override 402 protected Void doInBackground(Integer... params) { 403 // Sanity check mState 404 switch (mState) { 405 case NfcAdapter.STATE_TURNING_OFF: 406 case NfcAdapter.STATE_TURNING_ON: 407 Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " + 408 mState); 409 return null; 410 } 411 412 /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND, 413 * override with the default. THREAD_PRIORITY_BACKGROUND causes 414 * us to service software I2C too slow for firmware download 415 * with the NXP PN544. 416 * TODO: move this to the DAL I2C layer in libnfc-nxp, since this 417 * problem only occurs on I2C platforms using PN544 418 */ 419 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 420 421 switch (params[0].intValue()) { 422 case TASK_ENABLE: 423 enableInternal(); 424 break; 425 case TASK_DISABLE: 426 disableInternal(); 427 break; 428 case TASK_BOOT: 429 Log.d(TAG, "checking on firmware download"); 430 boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false); 431 if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) && 432 (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) { 433 Log.d(TAG, "NFC is on. Doing normal stuff"); 434 enableInternal(); 435 } else { 436 Log.d(TAG, "NFC is off. Checking firmware version"); 437 mDeviceHost.checkFirmware(); 438 } 439 if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) { 440 Log.i(TAG, "First Boot"); 441 mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false); 442 mPrefsEditor.apply(); 443 } 444 break; 445 } 446 447 // Restore default AsyncTask priority 448 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 449 return null; 450 } 451 452 /** 453 * Enable NFC adapter functions. 454 * Does not toggle preferences. 455 */ 456 boolean enableInternal() { 457 if (mState == NfcAdapter.STATE_ON) { 458 return true; 459 } 460 Log.i(TAG, "Enabling NFC"); 461 updateState(NfcAdapter.STATE_TURNING_ON); 462 463 WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS); 464 watchDog.start(); 465 try { 466 mRoutingWakeLock.acquire(); 467 try { 468 if (!mDeviceHost.initialize(mLockscreenDispatchEnabled)) { 469 Log.w(TAG, "Error enabling NFC"); 470 updateState(NfcAdapter.STATE_OFF); 471 return false; 472 } 473 } finally { 474 mRoutingWakeLock.release(); 475 } 476 } finally { 477 watchDog.cancel(); 478 } 479 480 if (mIsHceCapable) { 481 // Generate the initial card emulation routing table 482 mCardEmulationManager.onNfcEnabled(); 483 } 484 485 synchronized (NfcService.this) { 486 mObjectMap.clear(); 487 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true); 488 updateState(NfcAdapter.STATE_ON); 489 } 490 491 initSoundPool(); 492 493 /* Start polling loop */ 494 495 applyRouting(true); 496 return true; 497 } 498 499 /** 500 * Disable all NFC adapter functions. 501 * Does not toggle preferences. 502 */ 503 boolean disableInternal() { 504 if (mState == NfcAdapter.STATE_OFF) { 505 return true; 506 } 507 Log.i(TAG, "Disabling NFC"); 508 updateState(NfcAdapter.STATE_TURNING_OFF); 509 510 /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog. 511 * Implemented with a new thread (instead of a Handler or AsyncTask), 512 * because the UI Thread and AsyncTask thread-pools can also get hung 513 * when the NFC controller stops responding */ 514 WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS); 515 watchDog.start(); 516 517 if (mIsHceCapable) { 518 mCardEmulationManager.onNfcDisabled(); 519 } 520 521 mP2pLinkManager.enableDisable(false, false); 522 523 // Stop watchdog if tag present 524 // A convenient way to stop the watchdog properly consists of 525 // disconnecting the tag. The polling loop shall be stopped before 526 // to avoid the tag being discovered again. 527 maybeDisconnectTarget(); 528 529 mNfcDispatcher.setForegroundDispatch(null, null, null); 530 531 boolean result = mDeviceHost.deinitialize(); 532 if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result); 533 534 watchDog.cancel(); 535 536 updateState(NfcAdapter.STATE_OFF); 537 538 releaseSoundPool(); 539 540 return result; 541 } 542 543 void updateState(int newState) { 544 synchronized (NfcService.this) { 545 if (newState == mState) { 546 return; 547 } 548 mState = newState; 549 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 550 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 551 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState); 552 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 553 } 554 } 555 } 556 557 void saveNfcOnSetting(boolean on) { 558 synchronized (NfcService.this) { 559 mPrefsEditor.putBoolean(PREF_NFC_ON, on); 560 mPrefsEditor.apply(); 561 } 562 } 563 564 public void playSound(int sound) { 565 synchronized (this) { 566 if (mSoundPool == null) { 567 Log.w(TAG, "Not playing sound when NFC is disabled"); 568 return; 569 } 570 switch (sound) { 571 case SOUND_START: 572 mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f); 573 break; 574 case SOUND_END: 575 mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f); 576 break; 577 case SOUND_ERROR: 578 mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f); 579 break; 580 } 581 } 582 } 583 584 synchronized int getUserId() { 585 return mUserId; 586 } 587 588 589 final class NfcAdapterService extends INfcAdapter.Stub { 590 @Override 591 public boolean enable() throws RemoteException { 592 NfcPermissions.enforceAdminPermissions(mContext); 593 594 saveNfcOnSetting(true); 595 596 if (mIsAirplaneSensitive && isAirplaneModeOn()) { 597 if (!mIsAirplaneToggleable) { 598 Log.i(TAG, "denying enable() request (airplane mode)"); 599 return false; 600 } 601 // Make sure the override survives a reboot 602 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true); 603 mPrefsEditor.apply(); 604 } 605 new EnableDisableTask().execute(TASK_ENABLE); 606 607 return true; 608 } 609 610 @Override 611 public boolean disable(boolean saveState) throws RemoteException { 612 NfcPermissions.enforceAdminPermissions(mContext); 613 614 if (saveState) { 615 saveNfcOnSetting(false); 616 } 617 618 new EnableDisableTask().execute(TASK_DISABLE); 619 620 return true; 621 } 622 623 @Override 624 public boolean isNdefPushEnabled() throws RemoteException { 625 synchronized (NfcService.this) { 626 return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled; 627 } 628 } 629 630 @Override 631 public boolean enableNdefPush() throws RemoteException { 632 NfcPermissions.enforceAdminPermissions(mContext); 633 synchronized (NfcService.this) { 634 if (mIsNdefPushEnabled) { 635 return true; 636 } 637 Log.i(TAG, "enabling NDEF Push"); 638 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true); 639 mPrefsEditor.apply(); 640 mIsNdefPushEnabled = true; 641 if (isNfcEnabled()) { 642 mP2pLinkManager.enableDisable(true, true); 643 } 644 } 645 return true; 646 } 647 648 @Override 649 public boolean disableNdefPush() throws RemoteException { 650 NfcPermissions.enforceAdminPermissions(mContext); 651 synchronized (NfcService.this) { 652 if (!mIsNdefPushEnabled) { 653 return true; 654 } 655 Log.i(TAG, "disabling NDEF Push"); 656 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false); 657 mPrefsEditor.apply(); 658 mIsNdefPushEnabled = false; 659 if (isNfcEnabled()) { 660 mP2pLinkManager.enableDisable(false, true); 661 } 662 } 663 return true; 664 } 665 666 @Override 667 public void setForegroundDispatch(PendingIntent intent, 668 IntentFilter[] filters, TechListParcel techListsParcel) { 669 NfcPermissions.enforceUserPermissions(mContext); 670 671 // Short-cut the disable path 672 if (intent == null && filters == null && techListsParcel == null) { 673 mNfcDispatcher.setForegroundDispatch(null, null, null); 674 return; 675 } 676 677 // Validate the IntentFilters 678 if (filters != null) { 679 if (filters.length == 0) { 680 filters = null; 681 } else { 682 for (IntentFilter filter : filters) { 683 if (filter == null) { 684 throw new IllegalArgumentException("null IntentFilter"); 685 } 686 } 687 } 688 } 689 690 // Validate the tech lists 691 String[][] techLists = null; 692 if (techListsParcel != null) { 693 techLists = techListsParcel.getTechLists(); 694 } 695 696 mNfcDispatcher.setForegroundDispatch(intent, filters, techLists); 697 } 698 699 700 @Override 701 public void setAppCallback(IAppCallback callback) { 702 NfcPermissions.enforceUserPermissions(mContext); 703 mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid()); 704 } 705 706 @Override 707 public void invokeBeam() { 708 NfcPermissions.enforceUserPermissions(mContext); 709 710 if (mForegroundUtils.isInForeground(Binder.getCallingUid())) { 711 mP2pLinkManager.onManualBeamInvoke(null); 712 } else { 713 Log.e(TAG, "Calling activity not in foreground."); 714 } 715 } 716 717 @Override 718 public void invokeBeamInternal(BeamShareData shareData) { 719 NfcPermissions.enforceAdminPermissions(mContext); 720 Message msg = Message.obtain(); 721 msg.what = MSG_INVOKE_BEAM; 722 msg.obj = shareData; 723 // We have to send this message delayed for two reasons: 724 // 1) This is an IPC call from BeamShareActivity, which is 725 // running when the user has invoked Beam through the 726 // share menu. As soon as BeamShareActivity closes, the UI 727 // will need some time to rebuild the original Activity. 728 // Waiting here for a while gives a better chance of the UI 729 // having been rebuilt, which means the screenshot that the 730 // Beam animation is using will be more accurate. 731 // 2) Similarly, because the Activity that launched BeamShareActivity 732 // with an ACTION_SEND intent is now in paused state, the NDEF 733 // callbacks that it has registered may no longer be valid. 734 // Allowing the original Activity to resume will make sure we 735 // it has a chance to re-register the NDEF message / callback, 736 // so we share the right data. 737 // 738 // Note that this is somewhat of a hack because the delay may not actually 739 // be long enough for 2) on very slow devices, but there's no better 740 // way to do this right now without additional framework changes. 741 mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS); 742 } 743 744 @Override 745 public INfcTag getNfcTagInterface() throws RemoteException { 746 return mNfcTagService; 747 } 748 749 @Override 750 public INfcCardEmulation getNfcCardEmulationInterface() { 751 if (mIsHceCapable) { 752 return mCardEmulationManager.getNfcCardEmulationInterface(); 753 } else { 754 return null; 755 } 756 } 757 758 @Override 759 public int getState() throws RemoteException { 760 synchronized (NfcService.this) { 761 return mState; 762 } 763 } 764 765 @Override 766 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 767 NfcService.this.dump(fd, pw, args); 768 } 769 770 @Override 771 public void dispatch(Tag tag) throws RemoteException { 772 NfcPermissions.enforceAdminPermissions(mContext); 773 mNfcDispatcher.dispatchTag(tag); 774 } 775 776 @Override 777 public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException { 778 NfcPermissions.enforceAdminPermissions(mContext); 779 mDeviceHost.setP2pInitiatorModes(initiatorModes); 780 mDeviceHost.setP2pTargetModes(targetModes); 781 applyRouting(true); 782 } 783 784 @Override 785 public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras) 786 throws RemoteException { 787 synchronized (NfcService.this) { 788 if (flags != 0) { 789 try { 790 mReaderModeParams = new ReaderModeParams(); 791 mReaderModeParams.callback = callback; 792 mReaderModeParams.flags = flags; 793 mReaderModeParams.presenceCheckDelay = extras != null 794 ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 795 DEFAULT_PRESENCE_CHECK_DELAY)) 796 : DEFAULT_PRESENCE_CHECK_DELAY; 797 binder.linkToDeath(mReaderModeDeathRecipient, 0); 798 } catch (RemoteException e) { 799 Log.e(TAG, "Remote binder has already died."); 800 return; 801 } 802 } else { 803 try { 804 mReaderModeParams = null; 805 binder.unlinkToDeath(mReaderModeDeathRecipient, 0); 806 } catch (NoSuchElementException e) { 807 Log.e(TAG, "Reader mode Binder was never registered."); 808 } 809 } 810 applyRouting(false); 811 } 812 } 813 814 @Override 815 public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) throws RemoteException { 816 // nfc-extras implementation is no longer present in AOSP. 817 return null; 818 } 819 820 @Override 821 public void registerLockscreenDispatch(INfcLockscreenDispatch lockscreenDispatch, 822 int[] techList) 823 throws RemoteException { 824 825 NfcPermissions.enforceAdminPermissions(mContext); 826 827 boolean enableLockscreenDispatch = lockscreenDispatch != null; 828 int lockscreenPollMask; 829 830 if (enableLockscreenDispatch) { 831 lockscreenPollMask = computeLockscreenPollMask(techList); 832 mDeviceHost.enableScreenOffSuspend(); 833 } else { 834 lockscreenPollMask = 0; 835 mDeviceHost.disableScreenOffSuspend(); 836 } 837 838 synchronized (NfcService.this) { 839 mLockscreenPollMask = lockscreenPollMask; 840 mLockscreenDispatchEnabled = enableLockscreenDispatch; 841 mNfcDispatcher.registerLockscreenDispatch(lockscreenDispatch); 842 } 843 844 applyRouting(false); 845 } 846 847 private int computeLockscreenPollMask(int[] techList) { 848 849 Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>(); 850 851 techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A); 852 techCodeToMask.put(TagTechnology.NFC_B, 853 NfcService.NFC_POLL_B | NfcService.NFC_POLL_B_PRIME); 854 techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693); 855 techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F); 856 techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO); 857 858 int mask = 0; 859 860 for (int i = 0; i < techList.length; i++) { 861 if (techCodeToMask.containsKey(techList[i])) { 862 mask |= techCodeToMask.get(techList[i]).intValue(); 863 } 864 } 865 866 return mask; 867 } 868 } 869 870 final class ReaderModeDeathRecipient implements IBinder.DeathRecipient { 871 @Override 872 public void binderDied() { 873 synchronized (NfcService.this) { 874 if (mReaderModeParams != null) { 875 mReaderModeParams = null; 876 applyRouting(false); 877 } 878 } 879 } 880 } 881 882 final class TagService extends INfcTag.Stub { 883 @Override 884 public int close(int nativeHandle) throws RemoteException { 885 NfcPermissions.enforceUserPermissions(mContext); 886 887 TagEndpoint tag = null; 888 889 if (!isNfcEnabled()) { 890 return ErrorCodes.ERROR_NOT_INITIALIZED; 891 } 892 893 /* find the tag in the hmap */ 894 tag = (TagEndpoint) findObject(nativeHandle); 895 if (tag != null) { 896 /* Remove the device from the hmap */ 897 unregisterObject(nativeHandle); 898 tag.disconnect(); 899 return ErrorCodes.SUCCESS; 900 } 901 /* Restart polling loop for notification */ 902 applyRouting(true); 903 return ErrorCodes.ERROR_DISCONNECT; 904 } 905 906 @Override 907 public int connect(int nativeHandle, int technology) throws RemoteException { 908 NfcPermissions.enforceUserPermissions(mContext); 909 910 TagEndpoint tag = null; 911 912 if (!isNfcEnabled()) { 913 return ErrorCodes.ERROR_NOT_INITIALIZED; 914 } 915 916 /* find the tag in the hmap */ 917 tag = (TagEndpoint) findObject(nativeHandle); 918 if (tag == null) { 919 return ErrorCodes.ERROR_DISCONNECT; 920 } 921 922 if (!tag.isPresent()) { 923 return ErrorCodes.ERROR_DISCONNECT; 924 } 925 926 // Note that on most tags, all technologies are behind a single 927 // handle. This means that the connect at the lower levels 928 // will do nothing, as the tag is already connected to that handle. 929 if (tag.connect(technology)) { 930 return ErrorCodes.SUCCESS; 931 } else { 932 return ErrorCodes.ERROR_DISCONNECT; 933 } 934 } 935 936 @Override 937 public int reconnect(int nativeHandle) throws RemoteException { 938 NfcPermissions.enforceUserPermissions(mContext); 939 940 TagEndpoint tag = null; 941 942 // Check if NFC is enabled 943 if (!isNfcEnabled()) { 944 return ErrorCodes.ERROR_NOT_INITIALIZED; 945 } 946 947 /* find the tag in the hmap */ 948 tag = (TagEndpoint) findObject(nativeHandle); 949 if (tag != null) { 950 if (tag.reconnect()) { 951 return ErrorCodes.SUCCESS; 952 } else { 953 return ErrorCodes.ERROR_DISCONNECT; 954 } 955 } 956 return ErrorCodes.ERROR_DISCONNECT; 957 } 958 959 @Override 960 public int[] getTechList(int nativeHandle) throws RemoteException { 961 NfcPermissions.enforceUserPermissions(mContext); 962 963 // Check if NFC is enabled 964 if (!isNfcEnabled()) { 965 return null; 966 } 967 968 /* find the tag in the hmap */ 969 TagEndpoint tag = (TagEndpoint) findObject(nativeHandle); 970 if (tag != null) { 971 return tag.getTechList(); 972 } 973 return null; 974 } 975 976 @Override 977 public boolean isPresent(int nativeHandle) throws RemoteException { 978 TagEndpoint tag = null; 979 980 // Check if NFC is enabled 981 if (!isNfcEnabled()) { 982 return false; 983 } 984 985 /* find the tag in the hmap */ 986 tag = (TagEndpoint) findObject(nativeHandle); 987 if (tag == null) { 988 return false; 989 } 990 991 return tag.isPresent(); 992 } 993 994 @Override 995 public boolean isNdef(int nativeHandle) throws RemoteException { 996 NfcPermissions.enforceUserPermissions(mContext); 997 998 TagEndpoint tag = null; 999 1000 // Check if NFC is enabled 1001 if (!isNfcEnabled()) { 1002 return false; 1003 } 1004 1005 /* find the tag in the hmap */ 1006 tag = (TagEndpoint) findObject(nativeHandle); 1007 int[] ndefInfo = new int[2]; 1008 if (tag == null) { 1009 return false; 1010 } 1011 return tag.checkNdef(ndefInfo); 1012 } 1013 1014 @Override 1015 public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw) 1016 throws RemoteException { 1017 NfcPermissions.enforceUserPermissions(mContext); 1018 1019 TagEndpoint tag = null; 1020 byte[] response; 1021 1022 // Check if NFC is enabled 1023 if (!isNfcEnabled()) { 1024 return null; 1025 } 1026 1027 /* find the tag in the hmap */ 1028 tag = (TagEndpoint) findObject(nativeHandle); 1029 if (tag != null) { 1030 // Check if length is within limits 1031 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) { 1032 return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null); 1033 } 1034 int[] targetLost = new int[1]; 1035 response = tag.transceive(data, raw, targetLost); 1036 int result; 1037 if (response != null) { 1038 result = TransceiveResult.RESULT_SUCCESS; 1039 } else if (targetLost[0] == 1) { 1040 result = TransceiveResult.RESULT_TAGLOST; 1041 } else { 1042 result = TransceiveResult.RESULT_FAILURE; 1043 } 1044 return new TransceiveResult(result, response); 1045 } 1046 return null; 1047 } 1048 1049 @Override 1050 public NdefMessage ndefRead(int nativeHandle) throws RemoteException { 1051 NfcPermissions.enforceUserPermissions(mContext); 1052 1053 TagEndpoint tag; 1054 1055 // Check if NFC is enabled 1056 if (!isNfcEnabled()) { 1057 return null; 1058 } 1059 1060 /* find the tag in the hmap */ 1061 tag = (TagEndpoint) findObject(nativeHandle); 1062 if (tag != null) { 1063 byte[] buf = tag.readNdef(); 1064 if (buf == null) { 1065 return null; 1066 } 1067 1068 /* Create an NdefMessage */ 1069 try { 1070 return new NdefMessage(buf); 1071 } catch (FormatException e) { 1072 return null; 1073 } 1074 } 1075 return null; 1076 } 1077 1078 @Override 1079 public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException { 1080 NfcPermissions.enforceUserPermissions(mContext); 1081 1082 TagEndpoint tag; 1083 1084 // Check if NFC is enabled 1085 if (!isNfcEnabled()) { 1086 return ErrorCodes.ERROR_NOT_INITIALIZED; 1087 } 1088 1089 /* find the tag in the hmap */ 1090 tag = (TagEndpoint) findObject(nativeHandle); 1091 if (tag == null) { 1092 return ErrorCodes.ERROR_IO; 1093 } 1094 1095 if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM; 1096 1097 if (tag.writeNdef(msg.toByteArray())) { 1098 return ErrorCodes.SUCCESS; 1099 } else { 1100 return ErrorCodes.ERROR_IO; 1101 } 1102 1103 } 1104 1105 @Override 1106 public boolean ndefIsWritable(int nativeHandle) throws RemoteException { 1107 throw new UnsupportedOperationException(); 1108 } 1109 1110 @Override 1111 public int ndefMakeReadOnly(int nativeHandle) throws RemoteException { 1112 NfcPermissions.enforceUserPermissions(mContext); 1113 1114 TagEndpoint tag; 1115 1116 // Check if NFC is enabled 1117 if (!isNfcEnabled()) { 1118 return ErrorCodes.ERROR_NOT_INITIALIZED; 1119 } 1120 1121 /* find the tag in the hmap */ 1122 tag = (TagEndpoint) findObject(nativeHandle); 1123 if (tag == null) { 1124 return ErrorCodes.ERROR_IO; 1125 } 1126 1127 if (tag.makeReadOnly()) { 1128 return ErrorCodes.SUCCESS; 1129 } else { 1130 return ErrorCodes.ERROR_IO; 1131 } 1132 } 1133 1134 @Override 1135 public int formatNdef(int nativeHandle, byte[] key) throws RemoteException { 1136 NfcPermissions.enforceUserPermissions(mContext); 1137 1138 TagEndpoint tag; 1139 1140 // Check if NFC is enabled 1141 if (!isNfcEnabled()) { 1142 return ErrorCodes.ERROR_NOT_INITIALIZED; 1143 } 1144 1145 /* find the tag in the hmap */ 1146 tag = (TagEndpoint) findObject(nativeHandle); 1147 if (tag == null) { 1148 return ErrorCodes.ERROR_IO; 1149 } 1150 1151 if (tag.formatNdef(key)) { 1152 return ErrorCodes.SUCCESS; 1153 } else { 1154 return ErrorCodes.ERROR_IO; 1155 } 1156 } 1157 1158 @Override 1159 public Tag rediscover(int nativeHandle) throws RemoteException { 1160 NfcPermissions.enforceUserPermissions(mContext); 1161 1162 TagEndpoint tag = null; 1163 1164 // Check if NFC is enabled 1165 if (!isNfcEnabled()) { 1166 return null; 1167 } 1168 1169 /* find the tag in the hmap */ 1170 tag = (TagEndpoint) findObject(nativeHandle); 1171 if (tag != null) { 1172 // For now the prime usecase for rediscover() is to be able 1173 // to access the NDEF technology after formatting without 1174 // having to remove the tag from the field, or similar 1175 // to have access to NdefFormatable in case low-level commands 1176 // were used to remove NDEF. So instead of doing a full stack 1177 // rediscover (which is poorly supported at the moment anyway), 1178 // we simply remove these two technologies and detect them 1179 // again. 1180 tag.removeTechnology(TagTechnology.NDEF); 1181 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE); 1182 tag.findAndReadNdef(); 1183 // Build a new Tag object to return 1184 Tag newTag = new Tag(tag.getUid(), tag.getTechList(), 1185 tag.getTechExtras(), tag.getHandle(), this); 1186 return newTag; 1187 } 1188 return null; 1189 } 1190 1191 @Override 1192 public int setTimeout(int tech, int timeout) throws RemoteException { 1193 NfcPermissions.enforceUserPermissions(mContext); 1194 boolean success = mDeviceHost.setTimeout(tech, timeout); 1195 if (success) { 1196 return ErrorCodes.SUCCESS; 1197 } else { 1198 return ErrorCodes.ERROR_INVALID_PARAM; 1199 } 1200 } 1201 1202 @Override 1203 public int getTimeout(int tech) throws RemoteException { 1204 NfcPermissions.enforceUserPermissions(mContext); 1205 1206 return mDeviceHost.getTimeout(tech); 1207 } 1208 1209 @Override 1210 public void resetTimeouts() throws RemoteException { 1211 NfcPermissions.enforceUserPermissions(mContext); 1212 1213 mDeviceHost.resetTimeouts(); 1214 } 1215 1216 @Override 1217 public boolean canMakeReadOnly(int ndefType) throws RemoteException { 1218 return mDeviceHost.canMakeReadOnly(ndefType); 1219 } 1220 1221 @Override 1222 public int getMaxTransceiveLength(int tech) throws RemoteException { 1223 return mDeviceHost.getMaxTransceiveLength(tech); 1224 } 1225 1226 @Override 1227 public boolean getExtendedLengthApdusSupported() throws RemoteException { 1228 return mDeviceHost.getExtendedLengthApdusSupported(); 1229 } 1230 } 1231 1232 boolean isNfcEnabledOrShuttingDown() { 1233 synchronized (this) { 1234 return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF); 1235 } 1236 } 1237 1238 boolean isNfcEnabled() { 1239 synchronized (this) { 1240 return mState == NfcAdapter.STATE_ON; 1241 } 1242 } 1243 1244 class WatchDogThread extends Thread { 1245 final Object mCancelWaiter = new Object(); 1246 final int mTimeout; 1247 boolean mCanceled = false; 1248 1249 public WatchDogThread(String threadName, int timeout) { 1250 super(threadName); 1251 mTimeout = timeout; 1252 } 1253 1254 @Override 1255 public void run() { 1256 try { 1257 synchronized (mCancelWaiter) { 1258 mCancelWaiter.wait(mTimeout); 1259 if (mCanceled) { 1260 return; 1261 } 1262 } 1263 } catch (InterruptedException e) { 1264 // Should not happen; fall-through to abort. 1265 Log.w(TAG, "Watchdog thread interruped."); 1266 interrupt(); 1267 } 1268 Log.e(TAG, "Watchdog triggered, aborting."); 1269 mDeviceHost.doAbort(); 1270 } 1271 1272 public synchronized void cancel() { 1273 synchronized (mCancelWaiter) { 1274 mCanceled = true; 1275 mCancelWaiter.notify(); 1276 } 1277 } 1278 } 1279 1280 static byte[] hexStringToBytes(String s) { 1281 if (s == null || s.length() == 0) return null; 1282 int len = s.length(); 1283 if (len % 2 != 0) { 1284 s = '0' + s; 1285 len++; 1286 } 1287 byte[] data = new byte[len / 2]; 1288 for (int i = 0; i < len; i += 2) { 1289 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 1290 + Character.digit(s.charAt(i + 1), 16)); 1291 } 1292 return data; 1293 } 1294 1295 /** 1296 * Read mScreenState and apply NFC-C polling and NFC-EE routing 1297 */ 1298 void applyRouting(boolean force) { 1299 synchronized (this) { 1300 if (!isNfcEnabledOrShuttingDown()) { 1301 return; 1302 } 1303 WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS); 1304 if (mInProvisionMode) { 1305 mInProvisionMode = Settings.Secure.getInt(mContentResolver, 1306 Settings.Global.DEVICE_PROVISIONED, 0) == 0; 1307 if (!mInProvisionMode) { 1308 // Notify dispatcher it's fine to dispatch to any package now 1309 // and allow handover transfers. 1310 mNfcDispatcher.disableProvisioningMode(); 1311 mHandoverManager.setEnabled(true); 1312 } 1313 } 1314 // Special case: if we're transitioning to unlocked state while 1315 // still talking to a tag, postpone re-configuration. 1316 if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) { 1317 Log.d(TAG, "Not updating discovery parameters, tag connected."); 1318 return; 1319 } 1320 1321 try { 1322 watchDog.start(); 1323 // Compute new polling parameters 1324 NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState); 1325 if (force || !newParams.equals(mCurrentDiscoveryParameters)) { 1326 if (newParams.shouldEnableDiscovery()) { 1327 boolean shouldRestart = mDiscoveryEnabled; 1328 mDeviceHost.enableDiscovery(newParams, shouldRestart); 1329 mDiscoveryEnabled = true; 1330 } else { 1331 mDeviceHost.disableDiscovery(); 1332 mDiscoveryEnabled = false; 1333 } 1334 mCurrentDiscoveryParameters = newParams; 1335 } else { 1336 Log.d(TAG, "Discovery configuration equal, not updating."); 1337 } 1338 } finally { 1339 watchDog.cancel(); 1340 } 1341 } 1342 } 1343 1344 private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) { 1345 // Recompute discovery parameters based on screen state 1346 NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder(); 1347 // Polling 1348 if (screenState >= NFC_POLLING_MODE) { 1349 // Check if reader-mode is enabled 1350 if (mReaderModeParams != null) { 1351 int techMask = 0; 1352 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0) 1353 techMask |= NFC_POLL_A; 1354 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0) 1355 techMask |= NFC_POLL_B; 1356 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0) 1357 techMask |= NFC_POLL_F; 1358 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0) 1359 techMask |= NFC_POLL_ISO15693; 1360 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0) 1361 techMask |= NFC_POLL_KOVIO; 1362 1363 paramsBuilder.setTechMask(techMask); 1364 paramsBuilder.setEnableReaderMode(true); 1365 } else { 1366 paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 1367 } 1368 } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) { 1369 paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); 1370 } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && 1371 mLockscreenDispatchEnabled) { 1372 // For lock-screen tags, no low-power polling 1373 paramsBuilder.setTechMask(mLockscreenPollMask); 1374 paramsBuilder.setEnableLowPowerDiscovery(false); 1375 } 1376 1377 if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) { 1378 // Host routing is always enabled at lock screen or later 1379 paramsBuilder.setEnableHostRouting(true); 1380 } 1381 return paramsBuilder.build(); 1382 } 1383 1384 private boolean isTagPresent() { 1385 for (Object object : mObjectMap.values()) { 1386 if (object instanceof TagEndpoint) { 1387 return ((TagEndpoint) object).isPresent(); 1388 } 1389 } 1390 return false; 1391 } 1392 /** 1393 * Disconnect any target if present 1394 */ 1395 void maybeDisconnectTarget() { 1396 if (!isNfcEnabledOrShuttingDown()) { 1397 return; 1398 } 1399 Object[] objectsToDisconnect; 1400 synchronized (this) { 1401 Object[] objectValues = mObjectMap.values().toArray(); 1402 // Copy the array before we clear mObjectMap, 1403 // just in case the HashMap values are backed by the same array 1404 objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length); 1405 mObjectMap.clear(); 1406 } 1407 for (Object o : objectsToDisconnect) { 1408 if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName()); 1409 if (o instanceof TagEndpoint) { 1410 // Disconnect from tags 1411 TagEndpoint tag = (TagEndpoint) o; 1412 tag.disconnect(); 1413 } else if (o instanceof NfcDepEndpoint) { 1414 // Disconnect from P2P devices 1415 NfcDepEndpoint device = (NfcDepEndpoint) o; 1416 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1417 // Remote peer is target, request disconnection 1418 device.disconnect(); 1419 } else { 1420 // Remote peer is initiator, we cannot disconnect 1421 // Just wait for field removal 1422 } 1423 } 1424 } 1425 } 1426 1427 Object findObject(int key) { 1428 synchronized (this) { 1429 Object device = mObjectMap.get(key); 1430 if (device == null) { 1431 Log.w(TAG, "Handle not found"); 1432 } 1433 return device; 1434 } 1435 } 1436 1437 void registerTagObject(TagEndpoint tag) { 1438 synchronized (this) { 1439 mObjectMap.put(tag.getHandle(), tag); 1440 } 1441 } 1442 1443 void unregisterObject(int handle) { 1444 synchronized (this) { 1445 mObjectMap.remove(handle); 1446 } 1447 } 1448 1449 /** 1450 * For use by code in this process 1451 */ 1452 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) 1453 throws LlcpException { 1454 return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength); 1455 } 1456 1457 /** 1458 * For use by code in this process 1459 */ 1460 public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn) 1461 throws LlcpException { 1462 return mDeviceHost.createLlcpConnectionlessSocket(sap, sn); 1463 } 1464 1465 /** 1466 * For use by code in this process 1467 */ 1468 public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw, 1469 int linearBufferLength) throws LlcpException { 1470 return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength); 1471 } 1472 1473 public void sendMockNdefTag(NdefMessage msg) { 1474 sendMessage(MSG_MOCK_NDEF, msg); 1475 } 1476 1477 public void routeAids(String aid, int route) { 1478 Message msg = mHandler.obtainMessage(); 1479 msg.what = MSG_ROUTE_AID; 1480 msg.arg1 = route; 1481 msg.obj = aid; 1482 mHandler.sendMessage(msg); 1483 } 1484 1485 public void unrouteAids(String aid) { 1486 sendMessage(MSG_UNROUTE_AID, aid); 1487 } 1488 1489 public void commitRouting() { 1490 mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING); 1491 } 1492 1493 public boolean sendData(byte[] data) { 1494 return mDeviceHost.sendRawFrame(data); 1495 } 1496 1497 void sendMessage(int what, Object obj) { 1498 Message msg = mHandler.obtainMessage(); 1499 msg.what = what; 1500 msg.obj = obj; 1501 mHandler.sendMessage(msg); 1502 } 1503 1504 final class NfcServiceHandler extends Handler { 1505 @Override 1506 public void handleMessage(Message msg) { 1507 switch (msg.what) { 1508 case MSG_ROUTE_AID: { 1509 int route = msg.arg1; 1510 String aid = (String) msg.obj; 1511 mDeviceHost.routeAid(hexStringToBytes(aid), route); 1512 // Restart polling config 1513 break; 1514 } 1515 case MSG_UNROUTE_AID: { 1516 String aid = (String) msg.obj; 1517 mDeviceHost.unrouteAid(hexStringToBytes(aid)); 1518 break; 1519 } 1520 case MSG_INVOKE_BEAM: { 1521 mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj); 1522 break; 1523 } 1524 case MSG_COMMIT_ROUTING: { 1525 applyRouting(true); 1526 break; 1527 } 1528 case MSG_MOCK_NDEF: { 1529 NdefMessage ndefMsg = (NdefMessage) msg.obj; 1530 Bundle extras = new Bundle(); 1531 extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg); 1532 extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0); 1533 extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY); 1534 extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER); 1535 Tag tag = Tag.createMockTag(new byte[]{0x00}, 1536 new int[]{TagTechnology.NDEF}, 1537 new Bundle[]{extras}); 1538 Log.d(TAG, "mock NDEF tag, starting corresponding activity"); 1539 Log.d(TAG, tag.toString()); 1540 boolean delivered = mNfcDispatcher.dispatchTag(tag); 1541 if (delivered) { 1542 playSound(SOUND_END); 1543 } else { 1544 playSound(SOUND_ERROR); 1545 } 1546 break; 1547 } 1548 1549 case MSG_NDEF_TAG: 1550 if (DBG) Log.d(TAG, "Tag detected, notifying applications"); 1551 TagEndpoint tag = (TagEndpoint) msg.obj; 1552 ReaderModeParams readerParams = null; 1553 int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY; 1554 DeviceHost.TagDisconnectedCallback callback = 1555 new DeviceHost.TagDisconnectedCallback() { 1556 @Override 1557 public void onTagDisconnected(long handle) { 1558 applyRouting(false); 1559 } 1560 }; 1561 synchronized (NfcService.this) { 1562 readerParams = mReaderModeParams; 1563 } 1564 if (readerParams != null) { 1565 presenceCheckDelay = readerParams.presenceCheckDelay; 1566 if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) { 1567 if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode"); 1568 tag.startPresenceChecking(presenceCheckDelay, callback); 1569 dispatchTagEndpoint(tag, readerParams); 1570 break; 1571 } 1572 } 1573 if (readerParams == null || 1574 (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 1575 playSound(SOUND_START); 1576 } 1577 if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) { 1578 // When these tags start containing NDEF, they will require 1579 // the stack to deal with them in a different way, since 1580 // they are activated only really shortly. 1581 // For now, don't consider NDEF on these. 1582 if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode"); 1583 tag.startPresenceChecking(presenceCheckDelay, callback); 1584 dispatchTagEndpoint(tag, readerParams); 1585 break; 1586 } 1587 NdefMessage ndefMsg = tag.findAndReadNdef(); 1588 1589 if (ndefMsg != null) { 1590 tag.startPresenceChecking(presenceCheckDelay, callback); 1591 dispatchTagEndpoint(tag, readerParams); 1592 } else { 1593 if (tag.reconnect()) { 1594 tag.startPresenceChecking(presenceCheckDelay, callback); 1595 dispatchTagEndpoint(tag, readerParams); 1596 } else { 1597 tag.disconnect(); 1598 playSound(SOUND_ERROR); 1599 } 1600 } 1601 break; 1602 case MSG_LLCP_LINK_ACTIVATION: 1603 if (mIsDebugBuild) { 1604 Intent actIntent = new Intent(ACTION_LLCP_UP); 1605 mContext.sendBroadcast(actIntent); 1606 } 1607 llcpActivated((NfcDepEndpoint) msg.obj); 1608 break; 1609 1610 case MSG_LLCP_LINK_DEACTIVATED: 1611 if (mIsDebugBuild) { 1612 Intent deactIntent = new Intent(ACTION_LLCP_DOWN); 1613 mContext.sendBroadcast(deactIntent); 1614 } 1615 NfcDepEndpoint device = (NfcDepEndpoint) msg.obj; 1616 boolean needsDisconnect = false; 1617 1618 Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop."); 1619 synchronized (NfcService.this) { 1620 /* Check if the device has been already unregistered */ 1621 if (mObjectMap.remove(device.getHandle()) != null) { 1622 /* Disconnect if we are initiator */ 1623 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1624 if (DBG) Log.d(TAG, "disconnecting from target"); 1625 needsDisconnect = true; 1626 } else { 1627 if (DBG) Log.d(TAG, "not disconnecting from initiator"); 1628 } 1629 } 1630 } 1631 if (needsDisconnect) { 1632 device.disconnect(); // restarts polling loop 1633 } 1634 1635 mP2pLinkManager.onLlcpDeactivated(); 1636 break; 1637 case MSG_LLCP_LINK_FIRST_PACKET: 1638 mP2pLinkManager.onLlcpFirstPacketReceived(); 1639 break; 1640 default: 1641 Log.e(TAG, "Unknown message received"); 1642 break; 1643 } 1644 } 1645 1646 private boolean llcpActivated(NfcDepEndpoint device) { 1647 Log.d(TAG, "LLCP Activation message"); 1648 1649 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) { 1650 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET"); 1651 if (device.connect()) { 1652 /* Check LLCP compliancy */ 1653 if (mDeviceHost.doCheckLlcp()) { 1654 /* Activate LLCP Link */ 1655 if (mDeviceHost.doActivateLlcp()) { 1656 if (DBG) Log.d(TAG, "Initiator Activate LLCP OK"); 1657 synchronized (NfcService.this) { 1658 // Register P2P device 1659 mObjectMap.put(device.getHandle(), device); 1660 } 1661 mP2pLinkManager.onLlcpActivated(); 1662 return true; 1663 } else { 1664 /* should not happen */ 1665 Log.w(TAG, "Initiator LLCP activation failed. Disconnect."); 1666 device.disconnect(); 1667 } 1668 } else { 1669 if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect."); 1670 device.disconnect(); 1671 } 1672 } else { 1673 if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted."); 1674 /* 1675 * The polling loop should have been restarted in failing 1676 * doConnect 1677 */ 1678 } 1679 } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) { 1680 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR"); 1681 /* Check LLCP compliancy */ 1682 if (mDeviceHost.doCheckLlcp()) { 1683 /* Activate LLCP Link */ 1684 if (mDeviceHost.doActivateLlcp()) { 1685 if (DBG) Log.d(TAG, "Target Activate LLCP OK"); 1686 synchronized (NfcService.this) { 1687 // Register P2P device 1688 mObjectMap.put(device.getHandle(), device); 1689 } 1690 mP2pLinkManager.onLlcpActivated(); 1691 return true; 1692 } 1693 } else { 1694 Log.w(TAG, "checkLlcp failed"); 1695 } 1696 } 1697 1698 return false; 1699 } 1700 1701 private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) { 1702 Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(), 1703 tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService); 1704 registerTagObject(tagEndpoint); 1705 if (readerParams != null) { 1706 try { 1707 if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) { 1708 playSound(SOUND_END); 1709 } 1710 if (readerParams.callback != null) { 1711 readerParams.callback.onTagDiscovered(tag); 1712 return; 1713 } else { 1714 // Follow normal dispatch below 1715 } 1716 } catch (RemoteException e) { 1717 Log.e(TAG, "Reader mode remote has died, falling back.", e); 1718 // Intentional fall-through 1719 } catch (Exception e) { 1720 // Catch any other exception 1721 Log.e(TAG, "App exception, not dispatching.", e); 1722 return; 1723 } 1724 } 1725 if (!mNfcDispatcher.dispatchTag(tag)) { 1726 unregisterObject(tagEndpoint.getHandle()); 1727 playSound(SOUND_ERROR); 1728 } else { 1729 playSound(SOUND_END); 1730 } 1731 } 1732 } 1733 1734 private NfcServiceHandler mHandler = new NfcServiceHandler(); 1735 1736 class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> { 1737 @Override 1738 protected Void doInBackground(Integer... params) { 1739 synchronized (NfcService.this) { 1740 if (params == null || params.length != 1) { 1741 // force apply current routing 1742 applyRouting(true); 1743 return null; 1744 } 1745 mScreenState = params[0].intValue(); 1746 1747 mRoutingWakeLock.acquire(); 1748 try { 1749 applyRouting(false); 1750 } finally { 1751 mRoutingWakeLock.release(); 1752 } 1753 return null; 1754 } 1755 } 1756 } 1757 1758 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1759 @Override 1760 public void onReceive(Context context, Intent intent) { 1761 String action = intent.getAction(); 1762 if (action.equals(Intent.ACTION_SCREEN_ON) 1763 || action.equals(Intent.ACTION_SCREEN_OFF) 1764 || action.equals(Intent.ACTION_USER_PRESENT)) { 1765 // Perform applyRouting() in AsyncTask to serialize blocking calls 1766 int screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1767 if (action.equals(Intent.ACTION_SCREEN_OFF)) { 1768 screenState = ScreenStateHelper.SCREEN_STATE_OFF; 1769 } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 1770 screenState = mKeyguard.isKeyguardLocked() 1771 ? ScreenStateHelper.SCREEN_STATE_ON_LOCKED 1772 : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1773 } else if (action.equals(Intent.ACTION_USER_PRESENT)) { 1774 screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; 1775 } 1776 new ApplyRoutingTask().execute(Integer.valueOf(screenState)); 1777 } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 1778 boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 1779 // Query the airplane mode from Settings.System just to make sure that 1780 // some random app is not sending this intent 1781 if (isAirplaneModeOn != isAirplaneModeOn()) { 1782 return; 1783 } 1784 if (!mIsAirplaneSensitive) { 1785 return; 1786 } 1787 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false); 1788 mPrefsEditor.apply(); 1789 if (isAirplaneModeOn) { 1790 new EnableDisableTask().execute(TASK_DISABLE); 1791 } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) { 1792 new EnableDisableTask().execute(TASK_ENABLE); 1793 } 1794 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 1795 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1796 synchronized (this) { 1797 mUserId = userId; 1798 } 1799 mP2pLinkManager.onUserSwitched(getUserId()); 1800 if (mIsHceCapable) { 1801 mCardEmulationManager.onUserSwitched(getUserId()); 1802 } 1803 } 1804 } 1805 }; 1806 1807 /** 1808 * Returns true if airplane mode is currently on 1809 */ 1810 boolean isAirplaneModeOn() { 1811 return Settings.System.getInt(mContentResolver, 1812 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 1813 } 1814 1815 /** 1816 * for debugging only - no i18n 1817 */ 1818 static String stateToString(int state) { 1819 switch (state) { 1820 case NfcAdapter.STATE_OFF: 1821 return "off"; 1822 case NfcAdapter.STATE_TURNING_ON: 1823 return "turning on"; 1824 case NfcAdapter.STATE_ON: 1825 return "on"; 1826 case NfcAdapter.STATE_TURNING_OFF: 1827 return "turning off"; 1828 default: 1829 return "<error>"; 1830 } 1831 } 1832 1833 void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1834 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1835 != PackageManager.PERMISSION_GRANTED) { 1836 pw.println("Permission Denial: can't dump nfc from from pid=" 1837 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1838 + " without permission " + android.Manifest.permission.DUMP); 1839 return; 1840 } 1841 1842 synchronized (this) { 1843 pw.println("mState=" + stateToString(mState)); 1844 pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled); 1845 pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState)); 1846 pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive); 1847 pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable); 1848 pw.println(mCurrentDiscoveryParameters); 1849 mP2pLinkManager.dump(fd, pw, args); 1850 if (mIsHceCapable) { 1851 mCardEmulationManager.dump(fd, pw, args); 1852 } 1853 mNfcDispatcher.dump(fd, pw, args); 1854 pw.println(mDeviceHost.dump()); 1855 } 1856 } 1857} 1858