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