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