1 /* 2 * Copyright (C) 2013 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.cardemulation; 18 19 import android.annotation.TargetApi; 20 import android.annotation.FlaggedApi; 21 import android.app.ActivityManager; 22 import android.app.KeyguardManager; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.ServiceConnection; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageManager; 29 import android.content.pm.PackageManager.NameNotFoundException; 30 import android.nfc.NfcAdapter; 31 import android.nfc.cardemulation.ApduServiceInfo; 32 import android.nfc.cardemulation.CardEmulation; 33 import android.nfc.cardemulation.HostApduService; 34 import android.nfc.cardemulation.PollingFrame; 35 import android.nfc.cardemulation.Utils; 36 import android.os.Bundle; 37 import android.os.Handler; 38 import android.os.IBinder; 39 import android.os.Looper; 40 import android.os.Message; 41 import android.os.Messenger; 42 import android.os.PowerManager; 43 import android.os.RemoteException; 44 import android.os.UserHandle; 45 import android.sysprop.NfcProperties; 46 import android.util.ArraySet; 47 import android.util.Log; 48 import android.util.Pair; 49 import android.util.proto.ProtoOutputStream; 50 51 import androidx.annotation.VisibleForTesting; 52 53 import com.android.nfc.ForegroundUtils; 54 import com.android.nfc.NfcInjector; 55 import com.android.nfc.NfcService; 56 import com.android.nfc.NfcStatsLog; 57 import com.android.nfc.cardemulation.RegisteredAidCache.AidResolveInfo; 58 import com.android.nfc.cardemulation.util.StatsdUtils; 59 import com.android.nfc.flags.Flags; 60 import com.android.nfc.proto.NfcEventProto; 61 62 import java.io.FileDescriptor; 63 import java.io.PrintWriter; 64 import java.util.ArrayList; 65 import java.util.Arrays; 66 import java.util.HashMap; 67 import java.util.HexFormat; 68 import java.util.List; 69 import java.util.Locale; 70 import java.util.Map; 71 import java.util.Objects; 72 import java.util.Set; 73 import java.util.regex.Pattern; 74 75 76 public class HostEmulationManager { 77 static final String TAG = "HostEmulationManager"; 78 static final boolean DBG = NfcProperties.debug_enabled().orElse(true); 79 80 static final int STATE_IDLE = 0; 81 static final int STATE_W4_SELECT = 1; 82 static final int STATE_W4_SERVICE = 2; 83 static final int STATE_W4_DEACTIVATE = 3; 84 static final int STATE_XFER = 4; 85 static final int STATE_POLLING_LOOP = 5; 86 87 /** Minimum AID length as per ISO7816 */ 88 static final int MINIMUM_AID_LENGTH = 5; 89 90 /** Length of Select APDU header including length byte */ 91 static final int SELECT_APDU_HDR_LENGTH = 5; 92 93 static final byte INSTR_SELECT = (byte)0xA4; 94 95 static final String ANDROID_HCE_AID = "A000000476416E64726F6964484345"; 96 static final String NDEF_V1_AID = "D2760000850100"; 97 static final String NDEF_V2_AID = "D2760000850101"; 98 static final byte[] ANDROID_HCE_RESPONSE = {0x14, (byte)0x81, 0x00, 0x00, (byte)0x90, 0x00}; 99 100 static final byte[] AID_NOT_FOUND = {0x6A, (byte)0x82}; 101 static final byte[] UNKNOWN_ERROR = {0x6F, 0x00}; 102 103 static final int CE_HCE_PAYMENT = 104 NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_PAYMENT; 105 static final int CE_HCE_OTHER = 106 NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_OTHER; 107 static final String NFC_PACKAGE = "com.android.nfc"; 108 static final String DATA_KEY = "data"; 109 static final int FIELD_OFF_IDLE_DELAY_MS = 2000; 110 static final int RE_ENABLE_OBSERVE_MODE_DELAY_MS = 2000; 111 112 final Context mContext; 113 final RegisteredAidCache mAidCache; 114 final Messenger mMessenger = new Messenger (new MessageHandler()); 115 final KeyguardManager mKeyguard; 116 final Object mLock; 117 final PowerManager mPowerManager; 118 private final Looper mLooper; 119 120 private final StatsdUtils mStatsdUtils; 121 122 // All variables below protected by mLock 123 124 // Variables below are for a non-payment service, 125 // that is typically only bound in the STATE_XFER state. 126 Messenger mService; 127 boolean mServiceBound = false; 128 ComponentName mServiceName = null; 129 int mServiceUserId; // The UserId of the non-payment service 130 ArrayList<PollingFrame> mPendingPollingLoopFrames = null; 131 ArrayList<PollingFrame> mUnprocessedPollingFrames = null; 132 Map<ComponentName, ArrayList<PollingFrame>> mPollingFramesToSend = null; 133 private Map<Integer, Map<String, List<ApduServiceInfo>>> mPollingLoopFilters; 134 private Map<Integer, Map<Pattern, List<ApduServiceInfo>>> mPollingLoopPatternFilters; 135 AutoDisableObserveModeRunnable mAutoDisableObserveModeRunnable = null; 136 137 // Variables below are for a payment service, 138 // which is typically bound persistently to improve on 139 // latency. 140 Messenger mPaymentService; 141 boolean mPaymentServiceBound = false; 142 143 boolean mEnableObserveModeAfterTransaction = false; 144 boolean mEnableObserveModeOnFieldOff = false; 145 ComponentName mPaymentServiceName = null; 146 int mPaymentServiceUserId; // The userId of the payment service 147 ComponentName mLastBoundPaymentServiceName; 148 149 // mActiveService denotes the service interface 150 // that is the current active one, until a new SELECT AID 151 // comes in that may be resolved to a different service. 152 // On deactivation, mActiveService stops being valid. 153 Messenger mActiveService; 154 ComponentName mActiveServiceName; 155 int mActiveServiceUserId; // The UserId of the current active one 156 157 String mLastSelectedAid; 158 int mState; 159 byte[] mSelectApdu; 160 Handler mHandler; 161 162 163 enum PollingLoopState { 164 EVALUATING_POLLING_LOOP, 165 FILTER_MATCHED, 166 DELIVERING_TO_PREFERRED 167 }; 168 169 PollingLoopState mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 170 171 // Runnable to return to an IDLE_STATE and reset preferred service. This should be run after we 172 // have left a field and gone a period of time without any HCE or polling frame data. 173 Runnable mReturnToIdleStateRunnable = new Runnable() { 174 @Override 175 public void run() { 176 synchronized (mLock) { 177 Log.d(TAG, "Have been outside field, returning to idle state"); 178 mPendingPollingLoopFrames = null; 179 mPollingFramesToSend = null; 180 mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 181 resetActiveService(); 182 mState = STATE_IDLE; 183 } 184 } 185 }; 186 187 // Runnable to re-enable observe mode after a transaction. This should be delayed after 188 // HCE is deactivated to ensure we don't receive another select AID. 189 Runnable mEnableObserveModeAfterTransactionRunnable = new Runnable() { 190 @Override 191 public void run() { 192 synchronized (mLock) { 193 Log.d(TAG, "re-enabling observe mode after transaction."); 194 mEnableObserveModeAfterTransaction = false; 195 mEnableObserveModeOnFieldOff = false; 196 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 197 adapter.setObserveModeEnabled(true); 198 } 199 } 200 }; 201 HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache)202 public HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache) { 203 this(context, looper, aidCache, new StatsdUtils(StatsdUtils.SE_NAME_HCE)); 204 } 205 206 @VisibleForTesting HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, StatsdUtils statsdUtils)207 HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, 208 StatsdUtils statsdUtils) { 209 mContext = context; 210 mLooper = looper; 211 mHandler = new Handler(looper); 212 mLock = new Object(); 213 mAidCache = aidCache; 214 mState = STATE_IDLE; 215 mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 216 mKeyguard = context.getSystemService(KeyguardManager.class); 217 mPowerManager = context.getSystemService(PowerManager.class); 218 mStatsdUtils = Flags.statsdCeEventsFlag() ? statsdUtils : null; 219 mPollingLoopFilters = new HashMap<Integer, Map<String, List<ApduServiceInfo>>>(); 220 mPollingLoopPatternFilters = new HashMap<Integer, Map<Pattern, List<ApduServiceInfo>>>(); 221 } 222 223 /** 224 * Preferred payment service changed 225 */ onPreferredPaymentServiceChanged(int userId, final ComponentName service)226 public void onPreferredPaymentServiceChanged(int userId, final ComponentName service) { 227 mHandler.post(() -> { 228 synchronized (mLock) { 229 if (!isHostCardEmulationActivated()) { 230 Log.d(TAG, "onPreferredPaymentServiceChanged, resetting active service"); 231 resetActiveService(); 232 } 233 if (service != null) { 234 bindPaymentServiceLocked(userId, service); 235 } else { 236 unbindPaymentServiceLocked(); 237 } 238 } 239 }); 240 } 241 getForegroundServiceOrDefault()242 private Messenger getForegroundServiceOrDefault() { 243 Pair<Messenger, ComponentName> pair = getForegroundServiceAndNameOrDefault(); 244 if (pair == null) { 245 return null; 246 } 247 return pair.first; 248 } 249 getForegroundServiceAndNameOrDefault()250 private Pair<Messenger, ComponentName> getForegroundServiceAndNameOrDefault() { 251 Pair<Integer, ComponentName> preferredService = mAidCache.getPreferredService(); 252 int preferredServiceUserId = preferredService.first != null ? 253 preferredService.first : -1; 254 ComponentName preferredServiceName = preferredService.second; 255 256 if (preferredServiceName == null || preferredServiceUserId < 0) { 257 return null; 258 } 259 260 return new Pair<>(bindServiceIfNeededLocked(preferredServiceUserId, preferredServiceName), 261 preferredServiceName); 262 } 263 264 265 @TargetApi(35) 266 @FlaggedApi(android.nfc.Flags.FLAG_NFC_OBSERVE_MODE) updateForShouldDefaultToObserveMode(boolean enabled)267 public void updateForShouldDefaultToObserveMode(boolean enabled) { 268 synchronized (mLock) { 269 if (!isHostCardEmulationActivated()) { 270 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 271 adapter.setObserveModeEnabled(enabled); 272 } else { 273 mEnableObserveModeAfterTransaction = enabled; 274 } 275 } 276 } 277 278 279 @TargetApi(35) 280 @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) updatePollingLoopFilters(int userId, List<ApduServiceInfo> services)281 public void updatePollingLoopFilters(int userId, List<ApduServiceInfo> services) { 282 HashMap<String, List<ApduServiceInfo>> pollingLoopFilters = 283 new HashMap<String, List<ApduServiceInfo>>(); 284 HashMap<Pattern, List<ApduServiceInfo>> pollingLoopPatternFilters = 285 new HashMap<Pattern, List<ApduServiceInfo>>(); 286 for (ApduServiceInfo serviceInfo : services) { 287 for (String plf : serviceInfo.getPollingLoopFilters()) { 288 List<ApduServiceInfo> list = 289 pollingLoopFilters.getOrDefault(plf, new ArrayList<ApduServiceInfo>()); 290 list.add(serviceInfo); 291 pollingLoopFilters.putIfAbsent(plf, list); 292 293 } 294 for (Pattern plpf : serviceInfo.getPollingLoopPatternFilters()) { 295 List<ApduServiceInfo> list = 296 pollingLoopPatternFilters.getOrDefault(plpf, 297 new ArrayList<ApduServiceInfo>()); 298 list.add(serviceInfo); 299 pollingLoopPatternFilters.putIfAbsent(plpf, list); 300 301 } 302 } 303 mPollingLoopFilters.put(Integer.valueOf(userId), pollingLoopFilters); 304 mPollingLoopPatternFilters.put(Integer.valueOf(userId), pollingLoopPatternFilters); 305 } 306 onObserveModeStateChange(boolean enabled)307 public void onObserveModeStateChange(boolean enabled) { 308 synchronized(mLock) { 309 if (!enabled && mAutoDisableObserveModeRunnable != null) { 310 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable); 311 mAutoDisableObserveModeRunnable = null; 312 } 313 } 314 } 315 316 317 class AutoDisableObserveModeRunnable implements Runnable { 318 Set<String> mServicePackageNames; AutoDisableObserveModeRunnable(ComponentName componentName)319 AutoDisableObserveModeRunnable(ComponentName componentName) { 320 mServicePackageNames = new ArraySet<>(1); 321 addServiceToList(componentName); 322 } 323 324 @Override run()325 public void run() { 326 synchronized(mLock) { 327 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 328 if (!adapter.isObserveModeEnabled()) { 329 return; 330 } 331 if (arePackagesInForeground()) { 332 return; 333 } 334 Log.w(TAG, "Observe mode not disabled and no application from the following " + 335 "packages are in the foreground: " + String.join(", ", mServicePackageNames)); 336 allowOneTransaction(); 337 } 338 } 339 340 addServiceToList(ComponentName service)341 void addServiceToList(ComponentName service) { 342 mServicePackageNames.add(service.getPackageName()); 343 } 344 arePackagesInForeground()345 boolean arePackagesInForeground() { 346 ActivityManager am = mContext.getSystemService(ActivityManager.class); 347 if (am == null) { 348 return false; 349 } 350 ForegroundUtils foregroundUtils = ForegroundUtils.getInstance(am); 351 if (foregroundUtils == null) { 352 return false; 353 } 354 PackageManager packageManager = mContext.getPackageManager(); 355 if (packageManager == null) { 356 return false; 357 } 358 for (Integer uid : foregroundUtils.getForegroundUids()) { 359 for (String packageName : packageManager.getPackagesForUid(uid)) { 360 if (packageName != null) { 361 for (String servicePackageName : mServicePackageNames) { 362 if (Objects.equals(servicePackageName, packageName)) { 363 return true; 364 } 365 } 366 } 367 } 368 } 369 return false; 370 } 371 } 372 sendFrameToServiceLocked(Messenger service, ComponentName name, PollingFrame frame)373 private void sendFrameToServiceLocked(Messenger service, ComponentName name, 374 PollingFrame frame) { 375 sendFramesToServiceLocked(service, name, Arrays.asList(frame)); 376 } 377 sendFramesToServiceLocked(Messenger service, ComponentName name, List<PollingFrame> frames)378 private void sendFramesToServiceLocked(Messenger service, ComponentName name, 379 List<PollingFrame> frames) { 380 if (service != null) { 381 sendPollingFramesToServiceLocked(service, new ArrayList<>(frames)); 382 } else { 383 mUnprocessedPollingFrames = new ArrayList<PollingFrame>(); 384 if (mPollingFramesToSend == null) { 385 mPollingFramesToSend = new HashMap<ComponentName, ArrayList<PollingFrame>>(); 386 } 387 if (mPollingFramesToSend.containsKey(name)) { 388 mPollingFramesToSend.get(name).addAll(frames); 389 } else { 390 mPollingFramesToSend.put(name, new ArrayList<>(frames)); 391 } 392 } 393 if (Flags.autoDisableObserveMode()) { 394 if (mAutoDisableObserveModeRunnable == null) { 395 mAutoDisableObserveModeRunnable = new AutoDisableObserveModeRunnable(name); 396 mHandler.postDelayed(mAutoDisableObserveModeRunnable, 3000); 397 } else { 398 mAutoDisableObserveModeRunnable.addServiceToList(name); 399 } 400 } 401 } 402 403 @TargetApi(35) 404 @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP) onPollingLoopDetected(List<PollingFrame> pollingFrames)405 public void onPollingLoopDetected(List<PollingFrame> pollingFrames) { 406 Log.d(TAG, "onPollingLoopDetected, size: " + pollingFrames.size()); 407 synchronized (mLock) { 408 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 409 // We need to have this check here in addition to the one in onFieldChangeDetected, 410 // because we can receive an OFF frame after the field change is detected. 411 if (!pollingFrames.isEmpty() 412 && pollingFrames.getLast().getType() == PollingFrame.POLLING_LOOP_TYPE_OFF) { 413 mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS); 414 } 415 416 if (mState == STATE_IDLE) { 417 mState = STATE_POLLING_LOOP; 418 } 419 int onCount = 0; 420 int offCount = 0; 421 int aCount = 0; 422 int bCount = 0; 423 if (mPendingPollingLoopFrames == null) { 424 mPendingPollingLoopFrames = new ArrayList<PollingFrame>(1); 425 } 426 for (PollingFrame pollingFrame : pollingFrames) { 427 if (mUnprocessedPollingFrames != null) { 428 mUnprocessedPollingFrames.add(pollingFrame); 429 } else if (pollingFrame.getType() 430 == PollingFrame.POLLING_LOOP_TYPE_F) { 431 Pair<Messenger, ComponentName> serviceAndName = 432 getForegroundServiceAndNameOrDefault(); 433 if (serviceAndName != null) { 434 sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second, 435 pollingFrame); 436 } 437 } else if (pollingFrame.getType() 438 == PollingFrame.POLLING_LOOP_TYPE_UNKNOWN) { 439 byte[] data = pollingFrame.getData(); 440 String dataStr = HexFormat.of().formatHex(data).toUpperCase(Locale.ROOT); 441 List<ApduServiceInfo> serviceInfos = 442 mPollingLoopFilters.get(ActivityManager.getCurrentUser()).get(dataStr); 443 Map<Pattern, List<ApduServiceInfo>> patternMappingForUser = 444 mPollingLoopPatternFilters.get(ActivityManager.getCurrentUser()); 445 Set<Pattern> patternSet = patternMappingForUser.keySet(); 446 List<Pattern> matchedPatterns = patternSet.stream() 447 .filter(p -> p.matcher(dataStr).matches()).toList(); 448 if (!matchedPatterns.isEmpty()) { 449 if (serviceInfos == null) { 450 serviceInfos = new ArrayList<ApduServiceInfo>(); 451 } 452 for (Pattern matchedPattern : matchedPatterns) { 453 serviceInfos.addAll(patternMappingForUser.get(matchedPattern)); 454 } 455 } 456 if (serviceInfos != null && serviceInfos.size() > 0) { 457 ApduServiceInfo serviceInfo; 458 if (serviceInfos.size() == 1) { 459 serviceInfo = serviceInfos.get(0); 460 } else { 461 serviceInfo = mAidCache.resolvePollingLoopFilterConflict(serviceInfos); 462 if (serviceInfo == null) { 463 /* If neither the foreground or payments service can handle the plf, 464 * pick the first in the list. */ 465 serviceInfo = serviceInfos.get(0); 466 } 467 } 468 if (serviceInfo.getShouldAutoTransact(dataStr)) { 469 allowOneTransaction(); 470 pollingFrame.setTriggeredAutoTransact(true); 471 } 472 UserHandle user = UserHandle.getUserHandleForUid(serviceInfo.getUid()); 473 if (serviceInfo.isOnHost()) { 474 Messenger service = bindServiceIfNeededLocked(user.getIdentifier(), 475 serviceInfo.getComponent()); 476 mPollingLoopState = PollingLoopState.FILTER_MATCHED; 477 sendFrameToServiceLocked(service, serviceInfo.getComponent(), 478 pollingFrame); 479 } 480 } else { 481 Pair<Messenger, ComponentName> serviceAndName = 482 getForegroundServiceAndNameOrDefault(); 483 if (serviceAndName != null) { 484 sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second, 485 pollingFrame); 486 } 487 } 488 489 if (mStatsdUtils != null) { 490 mStatsdUtils.tallyPollingFrame(dataStr, pollingFrame); 491 } 492 } else { 493 mPendingPollingLoopFrames.add(pollingFrame); 494 } 495 if (mStatsdUtils != null) { 496 mStatsdUtils.logPollingFrames(); 497 } 498 } 499 500 if (mPollingLoopState == PollingLoopState.EVALUATING_POLLING_LOOP) { 501 if (mPendingPollingLoopFrames.size() >= 3) { 502 for (PollingFrame frame : mPendingPollingLoopFrames) { 503 int type = frame.getType(); 504 switch (type) { 505 case PollingFrame.POLLING_LOOP_TYPE_A: 506 aCount++; 507 if (aCount > 3) { 508 mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED; 509 } 510 break; 511 case PollingFrame.POLLING_LOOP_TYPE_B: 512 bCount++; 513 if (bCount > 3) { 514 mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED; 515 } 516 break; 517 case PollingFrame.POLLING_LOOP_TYPE_ON: 518 onCount++; 519 break; 520 case PollingFrame.POLLING_LOOP_TYPE_OFF: 521 // Send the loop data if we've seen at least one on before an off. 522 offCount++; 523 if (onCount >= 2 && offCount >=2) { 524 mPollingLoopState = PollingLoopState.DELIVERING_TO_PREFERRED; 525 } 526 break; 527 default: 528 } 529 if (mPollingLoopState != PollingLoopState.EVALUATING_POLLING_LOOP) { 530 break; 531 } 532 } 533 } 534 } 535 536 if (mPollingLoopState == PollingLoopState.DELIVERING_TO_PREFERRED) { 537 Pair<Messenger, ComponentName> serviceAndName = 538 getForegroundServiceAndNameOrDefault(); 539 if (serviceAndName != null) { 540 sendFramesToServiceLocked(serviceAndName.first, serviceAndName.second, 541 mPendingPollingLoopFrames); 542 mPendingPollingLoopFrames = null; 543 } else { 544 Log.i(TAG, "No preferred service to deliver polling frames to," 545 + " allowing transaction."); 546 allowOneTransaction(); 547 } 548 } 549 } 550 } 551 allowOneTransaction()552 private void allowOneTransaction() { 553 Log.d(TAG, "disabling observe mode for one transaction."); 554 mEnableObserveModeAfterTransaction = true; 555 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 556 mHandler.post(() -> adapter.setObserveModeEnabled(false)); 557 } 558 559 /** 560 * Preferred foreground service changed 561 */ onPreferredForegroundServiceChanged(int userId, ComponentName service)562 public void onPreferredForegroundServiceChanged(int userId, ComponentName service) { 563 synchronized (mLock) { 564 if (!isHostCardEmulationActivated()) { 565 Log.d(TAG, "onPreferredForegroundServiceChanged, resetting active service"); 566 resetActiveService(); 567 } 568 if (service != null) { 569 bindServiceIfNeededLocked(userId, service); 570 } else { 571 unbindServiceIfNeededLocked(); 572 } 573 } 574 } 575 onFieldChangeDetected(boolean fieldOn)576 public void onFieldChangeDetected(boolean fieldOn) { 577 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 578 if (!fieldOn) { 579 mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS); 580 } 581 if (!fieldOn && mEnableObserveModeOnFieldOff && mEnableObserveModeAfterTransaction) { 582 Log.d(TAG, "Field off detected, will re-enable observe mode."); 583 mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable, 584 RE_ENABLE_OBSERVE_MODE_DELAY_MS); 585 } 586 } 587 onHostEmulationActivated()588 public void onHostEmulationActivated() { 589 Log.d(TAG, "notifyHostEmulationActivated"); 590 synchronized (mLock) { 591 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 592 // Regardless of what happens, if we're having a tap again 593 // activity up, close it 594 Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE); 595 intent.setPackage(NFC_PACKAGE); 596 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 597 if (mState != STATE_IDLE && mState != STATE_POLLING_LOOP) { 598 Log.e(TAG, "Got activation event in non-idle state"); 599 } 600 mState = STATE_W4_SELECT; 601 } 602 } 603 604 static private class UnroutableAidBugReportRunnable implements Runnable { 605 List<String> mUnroutedAids; 606 UnroutableAidBugReportRunnable(String aid)607 UnroutableAidBugReportRunnable(String aid) { 608 mUnroutedAids = new ArrayList<String>(1); 609 mUnroutedAids.add(aid); 610 } 611 addAid(String aid)612 void addAid(String aid) { 613 mUnroutedAids.add(aid); 614 } 615 @Override run()616 public void run() { 617 NfcService.getInstance().mNfcDiagnostics.takeBugReport( 618 "NFC tap failed." 619 + " (If you weren't using NFC, " 620 + "no need to submit this report.)", 621 "Couldn't route " + String.join(", ", mUnroutedAids)); 622 } 623 } 624 625 UnroutableAidBugReportRunnable mUnroutableAidBugReportRunnable = null; 626 onHostEmulationData(byte[] data)627 public void onHostEmulationData(byte[] data) { 628 Log.d(TAG, "notifyHostEmulationData"); 629 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 630 mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable); 631 String selectAid = findSelectAid(data); 632 ComponentName resolvedService = null; 633 ApduServiceInfo resolvedServiceInfo = null; 634 AidResolveInfo resolveInfo = null; 635 synchronized (mLock) { 636 if (mState == STATE_IDLE) { 637 Log.e(TAG, "Got data in idle state."); 638 return; 639 } else if (mState == STATE_W4_DEACTIVATE) { 640 Log.e(TAG, "Dropping APDU in STATE_W4_DECTIVATE"); 641 return; 642 } 643 if (selectAid != null) { 644 if (selectAid.equals(ANDROID_HCE_AID)) { 645 NfcService.getInstance().sendData(ANDROID_HCE_RESPONSE); 646 return; 647 } 648 resolveInfo = mAidCache.resolveAid(selectAid); 649 if (resolveInfo == null || resolveInfo.services.size() == 0) { 650 if (selectAid.equals(NDEF_V1_AID) || selectAid.equals(NDEF_V2_AID)) { 651 Log.w(TAG, "Can't route NDEF AID, sending AID_NOT_FOUND"); 652 } else if (!mPowerManager.isScreenOn()) { 653 Log.i(TAG, 654 "Screen is off, sending AID_NOT_FOUND, but not triggering bug report"); 655 } else { 656 Log.w(TAG, "Can't handle AID " + selectAid + " sending AID_NOT_FOUND"); 657 if (mUnroutableAidBugReportRunnable != null) { 658 mUnroutableAidBugReportRunnable.addAid(selectAid); 659 } else { 660 mUnroutableAidBugReportRunnable = 661 new UnroutableAidBugReportRunnable(selectAid); 662 /* Wait 1s to see if there is an alternate AID we can route before 663 * taking a bug report */ 664 mHandler.postDelayed(mUnroutableAidBugReportRunnable, 1000); 665 } 666 } 667 NfcInjector.getInstance().getNfcEventLog().logEvent( 668 NfcEventProto.EventType.newBuilder() 669 .setCeUnroutableAid( 670 NfcEventProto.NfcCeUnroutableAid.newBuilder() 671 .setAid(selectAid) 672 .build()) 673 .build()); 674 // Tell the remote we don't handle this AID 675 NfcService.getInstance().sendData(AID_NOT_FOUND); 676 return; 677 } else if (mUnroutableAidBugReportRunnable != null) { 678 /* If there is a pending bug report runnable, cancel it. */ 679 mHandler.removeCallbacks(mUnroutableAidBugReportRunnable); 680 mUnroutableAidBugReportRunnable = null; 681 } 682 mLastSelectedAid = selectAid; 683 if (resolveInfo.defaultService != null) { 684 // Resolve to default 685 // Check if resolvedService requires unlock 686 ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService; 687 if (mStatsdUtils != null) { 688 mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category); 689 mStatsdUtils.setCardEmulationEventUid(defaultServiceInfo.getUid()); 690 } 691 692 if ((defaultServiceInfo.requiresUnlock() 693 || NfcService.getInstance().isSecureNfcEnabled()) 694 && mKeyguard.isKeyguardLocked()) { 695 NfcService.getInstance().sendRequireUnlockIntent(); 696 NfcService.getInstance().sendData(AID_NOT_FOUND); 697 if (DBG) Log.d(TAG, "requiresUnlock()! show toast"); 698 if (mStatsdUtils != null) { 699 mStatsdUtils.logCardEmulationWrongSettingEvent(); 700 } 701 launchTapAgain(resolveInfo.defaultService, resolveInfo.category); 702 return; 703 } 704 if (defaultServiceInfo.requiresScreenOn() && !mPowerManager.isScreenOn()) { 705 NfcService.getInstance().sendData(AID_NOT_FOUND); 706 if (DBG) Log.d(TAG, "requiresScreenOn()!"); 707 if (mStatsdUtils != null) { 708 mStatsdUtils.logCardEmulationWrongSettingEvent(); 709 } 710 return; 711 } 712 // In no circumstance should this be an OffHostService - 713 // we should never get this AID on the host in the first place 714 if (!defaultServiceInfo.isOnHost()) { 715 Log.e(TAG, "AID that was meant to go off-host was routed to host." + 716 " Check routing table configuration."); 717 NfcService.getInstance().sendData(AID_NOT_FOUND); 718 if (mStatsdUtils != null) { 719 mStatsdUtils.logCardEmulationNoRoutingEvent(); 720 } 721 return; 722 } 723 resolvedService = defaultServiceInfo.getComponent(); 724 resolvedServiceInfo = defaultServiceInfo; 725 } else if (mActiveServiceName != null) { 726 for (ApduServiceInfo serviceInfo : resolveInfo.services) { 727 if (mActiveServiceName.equals(serviceInfo.getComponent())) { 728 resolvedService = mActiveServiceName; 729 resolvedServiceInfo = serviceInfo; 730 break; 731 } 732 } 733 } 734 if (resolvedService == null) { 735 // We have no default, and either one or more services. 736 // Ask the user to confirm. 737 // Just ignore all future APDUs until we resolve to only one 738 mState = STATE_W4_DEACTIVATE; 739 NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, selectAid); 740 if (mStatsdUtils != null) { 741 mStatsdUtils.setCardEmulationEventCategory(CardEmulation.CATEGORY_OTHER); 742 mStatsdUtils.logCardEmulationWrongSettingEvent(); 743 } 744 launchResolver((ArrayList<ApduServiceInfo>)resolveInfo.services, null, 745 resolveInfo.category); 746 return; 747 } 748 } 749 switch (mState) { 750 case STATE_W4_SELECT: 751 if (selectAid != null) { 752 int uid = resolvedServiceInfo.getUid(); 753 if (mStatsdUtils != null) { 754 mStatsdUtils.setCardEmulationEventUid(uid); 755 mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category); 756 } 757 UserHandle user = 758 UserHandle.getUserHandleForUid(uid); 759 Messenger existingService = 760 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService); 761 if (existingService != null) { 762 Log.d(TAG, "Binding to existing service"); 763 sendDataToServiceLocked(existingService, data); 764 } else { 765 // Waiting for service to be bound 766 Log.d(TAG, "Waiting for new service."); 767 // Queue SELECT APDU to be used 768 mSelectApdu = data; 769 mState = STATE_W4_SERVICE; 770 } 771 if (mStatsdUtils != null) { 772 mStatsdUtils.notifyCardEmulationEventWaitingForResponse(); 773 } else { 774 int statsdCategory = 775 resolveInfo.category.equals(CardEmulation.CATEGORY_PAYMENT) 776 ? CE_HCE_PAYMENT 777 : CE_HCE_OTHER; 778 NfcStatsLog.write( 779 NfcStatsLog.NFC_CARDEMULATION_OCCURRED, 780 statsdCategory, 781 "HCE", 782 uid); 783 } 784 } else { 785 Log.d(TAG, "Dropping non-select APDU in STATE_W4_SELECT"); 786 NfcService.getInstance().sendData(UNKNOWN_ERROR); 787 } 788 break; 789 case STATE_W4_SERVICE: 790 Log.d(TAG, "Unexpected APDU in STATE_W4_SERVICE"); 791 break; 792 case STATE_XFER: 793 if (selectAid != null) { 794 UserHandle user = 795 UserHandle.getUserHandleForUid(resolvedServiceInfo.getUid()); 796 Messenger existingService = 797 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService); 798 if (existingService != null) { 799 sendDataToServiceLocked(existingService, data); 800 } else { 801 // Waiting for service to be bound 802 mSelectApdu = data; 803 mState = STATE_W4_SERVICE; 804 } 805 } else if (mActiveService != null) { 806 // Regular APDU data 807 sendDataToServiceLocked(mActiveService, data); 808 } else { 809 // No SELECT AID and no active service. 810 Log.d(TAG, "Service no longer bound, dropping APDU"); 811 } 812 break; 813 } 814 } 815 } 816 onHostEmulationDeactivated()817 public void onHostEmulationDeactivated() { 818 Log.d(TAG, "notifyHostEmulationDeactivated"); 819 synchronized (mLock) { 820 if (mState == STATE_IDLE) { 821 Log.e(TAG, "Got deactivation event while in idle state"); 822 } 823 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_LINK_LOSS); 824 resetActiveService(); 825 mPendingPollingLoopFrames = null; 826 mPollingFramesToSend = null; 827 unbindServiceIfNeededLocked(); 828 mState = STATE_IDLE; 829 mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 830 831 if (mAutoDisableObserveModeRunnable != null) { 832 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable); 833 mAutoDisableObserveModeRunnable = null; 834 } 835 836 if (mEnableObserveModeAfterTransaction) { 837 Log.d(TAG, "HCE deactivated, will re-enable observe mode."); 838 mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable, 839 RE_ENABLE_OBSERVE_MODE_DELAY_MS); 840 } 841 842 if (mStatsdUtils != null) { 843 mStatsdUtils.logCardEmulationDeactivatedEvent(); 844 } 845 } 846 } 847 isHostCardEmulationActivated()848 public boolean isHostCardEmulationActivated() { 849 synchronized (mLock) { 850 return mState != STATE_IDLE && mState != STATE_POLLING_LOOP; 851 } 852 } 853 onOffHostAidSelected()854 public void onOffHostAidSelected() { 855 Log.d(TAG, "notifyOffHostAidSelected"); 856 synchronized (mLock) { 857 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 858 mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable); 859 if (mState != STATE_XFER || mActiveService == null) { 860 // Don't bother telling, we're not bound to any service yet 861 } else { 862 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 863 } 864 if (mEnableObserveModeAfterTransaction) { 865 Log.i(TAG, "OffHost AID selected, waiting for Field off to reenable observe mode"); 866 mEnableObserveModeOnFieldOff = true; 867 } 868 resetActiveService(); 869 unbindServiceIfNeededLocked(); 870 mState = STATE_W4_SELECT; 871 872 //close the TapAgainDialog 873 Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE); 874 intent.setPackage(NFC_PACKAGE); 875 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 876 } 877 } 878 bindServiceIfNeededLocked(int userId, ComponentName service)879 Messenger bindServiceIfNeededLocked(int userId, ComponentName service) { 880 if (service == null) { 881 Log.e(TAG, "service ComponentName is null"); 882 return null; 883 } 884 885 Pair<Integer, ComponentName> preferredPaymentService = 886 mAidCache.getPreferredPaymentService(); 887 int preferredPaymentUserId = preferredPaymentService.first != null ? 888 preferredPaymentService.first : -1; 889 ComponentName preferredPaymentServiceName = preferredPaymentService.second; 890 891 if (mPaymentServiceName != null && mPaymentServiceName.equals(service) 892 && mPaymentServiceUserId == userId) { 893 Log.d(TAG, "Service already bound as payment service."); 894 return mPaymentService; 895 } else if (!mPaymentServiceBound && preferredPaymentServiceName != null 896 && preferredPaymentServiceName.equals(service) 897 && preferredPaymentUserId == userId) { 898 Log.d(TAG, "Service should be bound as payment service but is not, binding now"); 899 bindPaymentServiceLocked(userId, preferredPaymentServiceName); 900 return null; 901 } else if (mServiceName != null && mServiceName.equals(service) 902 && mServiceUserId == userId) { 903 Log.d(TAG, "Service already bound as regular service."); 904 return mService; 905 } else { 906 Log.d(TAG, "Binding to service " + service + " for userid:" + userId); 907 if (mStatsdUtils != null) { 908 mStatsdUtils.notifyCardEmulationEventWaitingForService(); 909 } 910 unbindServiceIfNeededLocked(); 911 Intent aidIntent = new Intent(HostApduService.SERVICE_INTERFACE); 912 aidIntent.setComponent(service); 913 try { 914 mServiceBound = mContext.bindServiceAsUser(aidIntent, mConnection, 915 Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, 916 UserHandle.of(userId)); 917 if (!mServiceBound) { 918 Log.e(TAG, "Could not bind service."); 919 } else { 920 mServiceUserId = userId; 921 } 922 } catch (SecurityException e) { 923 Log.e(TAG, "Could not bind service due to security exception."); 924 } 925 return null; 926 } 927 } 928 sendDataToServiceLocked(Messenger service, byte[] data)929 void sendDataToServiceLocked(Messenger service, byte[] data) { 930 mState = STATE_XFER; 931 if (service != mActiveService) { 932 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 933 mActiveService = service; 934 if (service.equals(mPaymentService)) { 935 mActiveServiceName = mPaymentServiceName; 936 mActiveServiceUserId = mPaymentServiceUserId; 937 } else { 938 mActiveServiceName = mServiceName; 939 mActiveServiceUserId = mServiceUserId; 940 } 941 } 942 Message msg = Message.obtain(null, HostApduService.MSG_COMMAND_APDU); 943 Bundle dataBundle = new Bundle(); 944 dataBundle.putByteArray(DATA_KEY, data); 945 msg.setData(dataBundle); 946 msg.replyTo = mMessenger; 947 try { 948 mActiveService.send(msg); 949 } catch (RemoteException e) { 950 Log.e(TAG, "Remote service " + mActiveServiceName + " has died, dropping APDU", e); 951 } 952 } 953 sendPollingFramesToServiceLocked(Messenger service, ArrayList<PollingFrame> pollingFrames)954 void sendPollingFramesToServiceLocked(Messenger service, 955 ArrayList<PollingFrame> pollingFrames) { 956 if (!Objects.equals(service, mActiveService)) { 957 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 958 mActiveService = service; 959 if (service.equals(mPaymentService)) { 960 mActiveServiceName = mPaymentServiceName; 961 mActiveServiceUserId = mPaymentServiceUserId; 962 } else { 963 mActiveServiceName = mServiceName; 964 mActiveServiceUserId = mServiceUserId; 965 } 966 } 967 Message msg = Message.obtain(null, HostApduService.MSG_POLLING_LOOP); 968 Bundle msgData = new Bundle(); 969 msgData.putParcelableArrayList(HostApduService.KEY_POLLING_LOOP_FRAMES_BUNDLE, 970 pollingFrames); 971 msg.setData(msgData); 972 msg.replyTo = mMessenger; 973 if (mState == STATE_IDLE) { 974 mState = STATE_POLLING_LOOP; 975 } 976 try { 977 mActiveService.send(msg); 978 } catch (RemoteException e) { 979 Log.e(TAG, "Remote service " + mActiveServiceName + " has died, dropping frames", e); 980 allowOneTransaction(); 981 } 982 } 983 sendDeactivateToActiveServiceLocked(int reason)984 void sendDeactivateToActiveServiceLocked(int reason) { 985 if (mActiveService == null) return; 986 Message msg = Message.obtain(null, HostApduService.MSG_DEACTIVATED); 987 msg.arg1 = reason; 988 try { 989 mActiveService.send(msg); 990 } catch (RemoteException e) { 991 // Don't care 992 } 993 } 994 unbindPaymentServiceLocked()995 void unbindPaymentServiceLocked() { 996 Log.d(TAG, "Unbinding payment service"); 997 if (mPaymentServiceBound) { 998 try { 999 mContext.unbindService(mPaymentConnection); 1000 } catch (Exception e) { 1001 Log.w(TAG, "Failed to unbind payment service: " + mPaymentServiceName, e); 1002 } 1003 mPaymentServiceBound = false; 1004 } 1005 1006 mPaymentService = null; 1007 mPaymentServiceName = null; 1008 mPaymentServiceUserId = -1; 1009 } 1010 bindPaymentServiceLocked(int userId, ComponentName service)1011 void bindPaymentServiceLocked(int userId, ComponentName service) { 1012 unbindPaymentServiceLocked(); 1013 1014 Log.d(TAG, "Binding to payment service " + service + " for userid:" + userId); 1015 Intent intent = new Intent(HostApduService.SERVICE_INTERFACE); 1016 intent.setComponent(service); 1017 try { 1018 if (mContext.bindServiceAsUser(intent, mPaymentConnection, 1019 Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, 1020 UserHandle.of(userId))) { 1021 mPaymentServiceBound = true; 1022 mPaymentServiceUserId = userId; 1023 mLastBoundPaymentServiceName = service; 1024 } else { 1025 Log.e(TAG, "Could not bind (persistent) payment service."); 1026 } 1027 } catch (SecurityException e) { 1028 Log.e(TAG, "Could not bind service due to security exception."); 1029 } 1030 } 1031 unbindServiceIfNeededLocked()1032 void unbindServiceIfNeededLocked() { 1033 if (mServiceBound) { 1034 Log.d(TAG, "Unbinding from service " + mServiceName); 1035 try { 1036 mContext.unbindService(mConnection); 1037 } catch (Exception e) { 1038 Log.w(TAG, "Failed to unbind service " + mServiceName, e); 1039 } 1040 mServiceBound = false; 1041 } 1042 1043 mService = null; 1044 mServiceName = null; 1045 mServiceUserId = -1; 1046 } 1047 launchTapAgain(ApduServiceInfo service, String category)1048 void launchTapAgain(ApduServiceInfo service, String category) { 1049 Intent dialogIntent = new Intent(mContext, TapAgainDialog.class); 1050 dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, category); 1051 dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, service); 1052 dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1053 mContext.startActivityAsUser(dialogIntent, 1054 UserHandle.getUserHandleForUid(service.getUid())); 1055 } 1056 launchResolver(ArrayList<ApduServiceInfo> services, ComponentName failedComponent, String category)1057 void launchResolver(ArrayList<ApduServiceInfo> services, ComponentName failedComponent, 1058 String category) { 1059 Intent intent = new Intent(mContext, AppChooserActivity.class); 1060 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1061 intent.putParcelableArrayListExtra(AppChooserActivity.EXTRA_APDU_SERVICES, services); 1062 intent.putExtra(AppChooserActivity.EXTRA_CATEGORY, category); 1063 if (failedComponent != null) { 1064 intent.putExtra(AppChooserActivity.EXTRA_FAILED_COMPONENT, failedComponent); 1065 } 1066 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 1067 } 1068 findSelectAid(byte[] data)1069 String findSelectAid(byte[] data) { 1070 if (data == null || data.length < SELECT_APDU_HDR_LENGTH + MINIMUM_AID_LENGTH) { 1071 if (DBG) Log.d(TAG, "Data size too small for SELECT APDU"); 1072 return null; 1073 } 1074 // To accept a SELECT AID for dispatch, we require the following: 1075 // Class byte must be 0x00: logical channel set to zero, no secure messaging, no chaining 1076 // Instruction byte must be 0xA4: SELECT instruction 1077 // P1: must be 0x04: select by application identifier 1078 // P2: File control information is only relevant for higher-level application, 1079 // and we only support "first or only occurrence". 1080 if (data[0] == 0x00 && data[1] == INSTR_SELECT && data[2] == 0x04) { 1081 if (data[3] != 0x00) { 1082 Log.d(TAG, "Selecting next, last or previous AID occurrence is not supported"); 1083 } 1084 int aidLength = Byte.toUnsignedInt(data[4]); 1085 if (data.length < SELECT_APDU_HDR_LENGTH + aidLength) { 1086 return null; 1087 } 1088 return bytesToString(data, SELECT_APDU_HDR_LENGTH, aidLength); 1089 } 1090 return null; 1091 } 1092 resetActiveService()1093 private void resetActiveService() { 1094 mActiveService = null; 1095 mActiveServiceName = null; 1096 mActiveServiceUserId = -1; 1097 } 1098 1099 private ServiceConnection mPaymentConnection = new ServiceConnection() { 1100 @Override 1101 public void onServiceConnected(ComponentName name, IBinder service) { 1102 synchronized (mLock) { 1103 /* Preferred Payment Service has been changed. */ 1104 if (!mLastBoundPaymentServiceName.equals(name)) { 1105 Log.i(TAG, "Ignoring bound payment service, " + name + " != " 1106 + mLastBoundPaymentServiceName); 1107 return; 1108 } 1109 mPaymentServiceName = name; 1110 mPaymentService = new Messenger(service); 1111 Log.i(TAG, "Payment service bound: " + name); 1112 } 1113 } 1114 1115 @Override 1116 public void onServiceDisconnected(ComponentName name) { 1117 Log.i(TAG, "Payment service disconnected: " + name); 1118 synchronized (mLock) { 1119 mPaymentService = null; 1120 mPaymentServiceName = null; 1121 } 1122 } 1123 1124 @Override 1125 public void onBindingDied(ComponentName name) { 1126 Log.i(TAG, "Payment service died: " + name); 1127 synchronized (mLock) { 1128 bindPaymentServiceLocked(mPaymentServiceUserId, mLastBoundPaymentServiceName); 1129 } 1130 } 1131 }; 1132 1133 private ServiceConnection mConnection = new ServiceConnection() { 1134 @Override 1135 public void onServiceConnected(ComponentName name, IBinder service) { 1136 synchronized (mLock) { 1137 /* Service is already deactivated, don't bind */ 1138 if (mState == STATE_IDLE) { 1139 return; 1140 } 1141 mService = new Messenger(service); 1142 mServiceName = name; 1143 mServiceBound = true; 1144 Log.d(TAG, "Service bound: " + name); 1145 // Send pending select APDU 1146 if (mSelectApdu != null) { 1147 if (mStatsdUtils != null) { 1148 mStatsdUtils.notifyCardEmulationEventServiceBound(); 1149 } 1150 sendDataToServiceLocked(mService, mSelectApdu); 1151 mSelectApdu = null; 1152 } else if (mPollingFramesToSend != null && mPollingFramesToSend.containsKey(name)) { 1153 sendPollingFramesToServiceLocked(mService, mPollingFramesToSend.get(name)); 1154 mPollingFramesToSend.remove(name); 1155 if (android.nfc.Flags.nfcReadPollingLoop() 1156 && mUnprocessedPollingFrames != null) { 1157 ArrayList unprocessedPollingFrames = mUnprocessedPollingFrames; 1158 mUnprocessedPollingFrames = null; 1159 onPollingLoopDetected(unprocessedPollingFrames); 1160 } 1161 } else { 1162 Log.d(TAG, "bound with nothing to send"); 1163 } 1164 } 1165 } 1166 1167 @Override 1168 public void onServiceDisconnected(ComponentName name) { 1169 synchronized (mLock) { 1170 Log.d(TAG, "Service unbound: " + name); 1171 mService = null; 1172 mServiceName = null; 1173 mServiceBound = false; 1174 } 1175 } 1176 }; 1177 1178 class MessageHandler extends Handler { 1179 @Override handleMessage(Message msg)1180 public void handleMessage(Message msg) { 1181 synchronized(mLock) { 1182 if (mActiveService == null) { 1183 Log.d(TAG, "Dropping service response message; service no longer active."); 1184 return; 1185 } else if (!msg.replyTo.getBinder().equals(mActiveService.getBinder())) { 1186 Log.d(TAG, "Dropping service response message; service no longer bound."); 1187 return; 1188 } 1189 } 1190 if (msg.what == HostApduService.MSG_RESPONSE_APDU) { 1191 Bundle dataBundle = msg.getData(); 1192 if (dataBundle == null) { 1193 return; 1194 } 1195 byte[] data = dataBundle.getByteArray(DATA_KEY); 1196 if (data == null || data.length == 0) { 1197 Log.e(TAG, "Dropping empty R-APDU"); 1198 return; 1199 } 1200 int state; 1201 synchronized(mLock) { 1202 state = mState; 1203 } 1204 if (state == STATE_XFER) { 1205 Log.d(TAG, "Sending data"); 1206 NfcService.getInstance().sendData(data); 1207 if (mStatsdUtils != null) { 1208 mStatsdUtils.notifyCardEmulationEventResponseReceived(); 1209 } 1210 } else { 1211 Log.d(TAG, "Dropping data, wrong state " + Integer.toString(state)); 1212 } 1213 } else if (msg.what == HostApduService.MSG_UNHANDLED) { 1214 synchronized (mLock) { 1215 Log.d(TAG, "Received MSG_UNHANDLED"); 1216 AidResolveInfo resolveInfo = mAidCache.resolveAid(mLastSelectedAid); 1217 boolean isPayment = false; 1218 if (resolveInfo.services.size() > 0) { 1219 NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, mLastSelectedAid); 1220 launchResolver((ArrayList<ApduServiceInfo>)resolveInfo.services, 1221 mActiveServiceName, resolveInfo.category); 1222 } 1223 } 1224 } 1225 } 1226 } 1227 bytesToString(byte[] bytes, int offset, int length)1228 static String bytesToString(byte[] bytes, int offset, int length) { 1229 final char[] hexChars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 1230 char[] chars = new char[length * 2]; 1231 int byteValue; 1232 for (int j = 0; j < length; j++) { 1233 byteValue = bytes[offset + j] & 0xFF; 1234 chars[j * 2] = hexChars[byteValue >>> 4]; 1235 chars[j * 2 + 1] = hexChars[byteValue & 0x0F]; 1236 } 1237 return new String(chars); 1238 } 1239 dump(FileDescriptor fd, PrintWriter pw, String[] args)1240 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1241 pw.println("Bound HCE-A/HCE-B services: "); 1242 if (mPaymentServiceBound) { 1243 pw.println(" payment: " + mPaymentServiceName); 1244 } 1245 if (mServiceBound) { 1246 pw.println(" other: " + mServiceName); 1247 } 1248 } 1249 1250 /** 1251 * Dump debugging information as a HostEmulationManagerProto 1252 * 1253 * Note: 1254 * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto 1255 * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and 1256 * {@link ProtoOutputStream#end(long)} after. 1257 * Never reuse a proto field number. When removing a field, mark it as reserved. 1258 */ dumpDebug(ProtoOutputStream proto)1259 void dumpDebug(ProtoOutputStream proto) { 1260 if (mPaymentServiceBound) { 1261 Utils.dumpDebugComponentName( 1262 mPaymentServiceName, proto, HostEmulationManagerProto.PAYMENT_SERVICE_NAME); 1263 } 1264 if (mServiceBound) { 1265 Utils.dumpDebugComponentName( 1266 mServiceName, proto, HostEmulationManagerProto.SERVICE_NAME); 1267 } 1268 } 1269 1270 @VisibleForTesting getState()1271 public int getState(){ 1272 return mState; 1273 } 1274 1275 @VisibleForTesting getServiceConnection()1276 public ServiceConnection getServiceConnection(){ 1277 return mConnection; 1278 } 1279 1280 @VisibleForTesting getPaymentConnection()1281 public ServiceConnection getPaymentConnection(){ 1282 return mPaymentConnection; 1283 } 1284 1285 @VisibleForTesting getMessenger()1286 public IBinder getMessenger(){ 1287 if (mActiveService != null) { 1288 return mActiveService.getBinder(); 1289 } 1290 return null; 1291 } 1292 1293 @VisibleForTesting getLocalMessenger()1294 public Messenger getLocalMessenger() { 1295 return mMessenger; 1296 } 1297 1298 @VisibleForTesting getServiceName()1299 public ComponentName getServiceName(){ 1300 return mLastBoundPaymentServiceName; 1301 } 1302 1303 @VisibleForTesting isServiceBounded()1304 public Boolean isServiceBounded(){ 1305 return mServiceBound; 1306 } 1307 1308 @VisibleForTesting getPollingLoopFilters()1309 public Map<Integer, Map<String, List<ApduServiceInfo>>> getPollingLoopFilters() { 1310 return mPollingLoopFilters; 1311 } 1312 1313 @VisibleForTesting getPollingLoopPatternFilters()1314 public Map<Integer, Map<Pattern, List<ApduServiceInfo>>> getPollingLoopPatternFilters() { 1315 return mPollingLoopPatternFilters; 1316 } 1317 } 1318