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