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