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 static com.android.nfc.module.flags.Flags.nfcHceLatencyEvents; 20 21 import android.annotation.FlaggedApi; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.TargetApi; 25 import android.annotation.UserIdInt; 26 import android.app.ActivityManager; 27 import android.app.KeyguardManager; 28 import android.app.compat.CompatChanges; 29 import android.compat.annotation.ChangeId; 30 import android.compat.annotation.EnabledSince; 31 import android.content.ComponentName; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.ServiceConnection; 35 import android.content.pm.PackageManager; 36 import android.nfc.ComponentNameAndUser; 37 import android.nfc.INfcOemExtensionCallback; 38 import android.nfc.NfcAdapter; 39 import android.nfc.OemLogItems; 40 import android.nfc.cardemulation.ApduServiceInfo; 41 import android.nfc.cardemulation.CardEmulation; 42 import android.nfc.cardemulation.HostApduService; 43 import android.nfc.cardemulation.PollingFrame; 44 import android.nfc.cardemulation.Utils; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.IBinder; 48 import android.os.Looper; 49 import android.os.Message; 50 import android.os.Messenger; 51 import android.os.PowerManager; 52 import android.os.RemoteException; 53 import android.os.SystemClock; 54 import android.os.Trace; 55 import android.os.UserHandle; 56 import android.sysprop.NfcProperties; 57 import android.util.ArraySet; 58 import android.util.Log; 59 import android.util.Pair; 60 import android.util.proto.ProtoOutputStream; 61 62 import androidx.annotation.VisibleForTesting; 63 64 import com.android.nfc.DeviceConfigFacade; 65 import com.android.nfc.ForegroundUtils; 66 import com.android.nfc.NfcInjector; 67 import com.android.nfc.NfcService; 68 import com.android.nfc.NfcStatsLog; 69 import com.android.nfc.PerfettoTrigger; 70 import com.android.nfc.cardemulation.RegisteredAidCache.AidResolveInfo; 71 import com.android.nfc.cardemulation.util.StatsdUtils; 72 import com.android.nfc.flags.Flags; 73 import com.android.nfc.proto.NfcEventProto; 74 75 import java.io.FileDescriptor; 76 import java.io.PrintWriter; 77 import java.nio.ByteBuffer; 78 import java.util.ArrayList; 79 import java.util.Arrays; 80 import java.util.HashMap; 81 import java.util.HexFormat; 82 import java.util.List; 83 import java.util.Locale; 84 import java.util.Map; 85 import java.util.Objects; 86 import java.util.Random; 87 import java.util.Set; 88 import java.util.regex.Pattern; 89 90 public class HostEmulationManager { 91 static final String TAG = "HostEmulationManager"; 92 static final boolean DBG = NfcProperties.debug_enabled().orElse(true); 93 94 static final int STATE_IDLE = 0; 95 static final int STATE_W4_SELECT = 1; 96 static final int STATE_W4_SERVICE = 2; 97 static final int STATE_W4_DEACTIVATE = 3; 98 static final int STATE_XFER = 4; 99 static final int STATE_POLLING_LOOP = 5; 100 101 /** Minimum AID length as per ISO7816 */ 102 static final int MINIMUM_AID_LENGTH = 5; 103 104 /** Length of Select APDU header including length byte */ 105 static final int SELECT_APDU_HDR_LENGTH = 5; 106 107 static final byte INSTR_SELECT = (byte)0xA4; 108 109 static final String ANDROID_HCE_AID = "A000000476416E64726F6964484345"; 110 static final String NDEF_V1_AID = "D2760000850100"; 111 static final String NDEF_V2_AID = "D2760000850101"; 112 static final byte[] ANDROID_HCE_RESPONSE = {0x14, (byte)0x81, 0x00, 0x00, (byte)0x90, 0x00}; 113 114 static final byte[] AID_NOT_FOUND = {0x6A, (byte)0x82}; 115 static final byte[] UNKNOWN_ERROR = {0x6F, 0x00}; 116 117 static final int CE_HCE_PAYMENT = 118 NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_PAYMENT; 119 static final int CE_HCE_OTHER = 120 NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_OTHER; 121 static final String DATA_KEY = "data"; 122 static final int FIELD_OFF_IDLE_DELAY_MS = 2000; 123 static final int RE_ENABLE_OBSERVE_MODE_DELAY_MS = 2000; 124 static final int UNBIND_SERVICES_DELAY_MS = 10_000; 125 126 static final String EVENT_HCE_ACTIVATED = "hce_active"; 127 static final String EVENT_HCE_BIND_PAYMENT_SERVICE = "hce_bind_payment_service"; 128 static final String EVENT_HCE_BIND_SERVICE = "hce_bind_service"; 129 static final String EVENT_HCE_COMMAND_APDU = "hce_command_apdu"; 130 static final String EVENT_POLLING_FRAMES = "hce_polling_frames"; 131 static final String TRIGGER_NAME_SLOW_TAP = "android.nfc.slow-tap"; 132 133 final Context mContext; 134 final RegisteredAidCache mAidCache; 135 final Messenger mMessenger = new Messenger (new MessageHandler()); 136 final KeyguardManager mKeyguard; 137 final Object mLock; 138 final PowerManager mPowerManager; 139 private final Looper mLooper; 140 final DeviceConfigFacade mDeviceConfig; 141 142 @Nullable 143 private final StatsdUtils mStatsdUtils; 144 145 private final Random mCookieRandom = new Random(System.currentTimeMillis()); 146 147 @ChangeId 148 @EnabledSince(targetSdkVersion = 36 /*Build.VERSION_CODES.BAKLAVA*/) 149 static final long DONT_IMMEDIATELY_UNBIND_SERVICES = 365533082L; 150 151 INfcOemExtensionCallback mNfcOemExtensionCallback; 152 153 long mFieldOnTime; 154 155 // All variables below protected by mLock 156 157 // Variables below are for a non-payment service, 158 // that is typically only bound in the STATE_XFER state. 159 Messenger mService; 160 161 static class HostEmulationConnection { 162 @UserIdInt int mUserId; 163 ComponentName mComponentName; 164 ServiceConnection mServiceConnection; 165 Messenger mMessenger; 166 HostEmulationConnection(@serIdInt int userId, ComponentName componentName, ServiceConnection serviceConnection)167 HostEmulationConnection(@UserIdInt int userId, 168 ComponentName componentName, 169 ServiceConnection serviceConnection) { 170 this(userId, componentName, serviceConnection, null); 171 } 172 HostEmulationConnection( @serIdInt int userId, ComponentName componentName, ServiceConnection serviceConnection, Messenger messenger)173 HostEmulationConnection( 174 @UserIdInt int userId, 175 ComponentName componentName, 176 ServiceConnection serviceConnection, 177 Messenger messenger) { 178 mUserId = userId; 179 mComponentName = componentName; 180 mServiceConnection = serviceConnection; 181 mMessenger = messenger; 182 } 183 184 @Override toString()185 public String toString() { 186 return "{" + mComponentName + "(" + mUserId + "): " 187 + mMessenger + ", " + mServiceConnection + "}"; 188 } 189 } 190 191 Map<ComponentNameAndUser, HostEmulationConnection> mComponentNameToConnectionsMap = 192 new HashMap<>(); 193 boolean mServiceBound = false; 194 ComponentName mServiceName = null; 195 @UserIdInt int mServiceUserId; // The UserId of the non-payment service 196 ArrayList<PollingFrame> mPendingPollingLoopFrames = null; 197 ArrayList<PollingFrame> mUnprocessedPollingFrames = null; 198 Map<ComponentName, ArrayList<PollingFrame>> mPollingFramesToSend = null; 199 private Map<Integer, Map<String, List<ApduServiceInfo>>> mPollingLoopFilters; 200 private Map<Integer, Map<Pattern, List<ApduServiceInfo>>> mPollingLoopPatternFilters; 201 AutoDisableObserveModeRunnable mAutoDisableObserveModeRunnable = null; 202 203 // Variables below are for a payment service, 204 // which is typically bound persistently to improve on 205 // latency. 206 Messenger mPaymentService; 207 boolean mPaymentServiceBound = false; 208 209 boolean mEnableObserveModeAfterTransaction = false; 210 boolean mEnableObserveModeOnFieldOff = false; 211 PollingFrame mFirmwareExitFrame = null; 212 ComponentName mPaymentServiceName = null; 213 @UserIdInt int mPaymentServiceUserId; // The userId of the payment service 214 ComponentName mLastBoundPaymentServiceName; 215 216 // mActiveService denotes the service interface 217 // that is the current active one, until a new SELECT AID 218 // comes in that may be resolved to a different service. 219 // On deactivation, mActiveService stops being valid. 220 Messenger mActiveService; 221 ComponentName mActiveServiceName; 222 @UserIdInt int mActiveServiceUserId; // The UserId of the current active one 223 224 String mLastSelectedAid; 225 int mState; 226 byte[] mSelectApdu; 227 Handler mHandler; 228 229 230 enum PollingLoopState { 231 EVALUATING_POLLING_LOOP, 232 FILTER_MATCHED, 233 DELIVERING_TO_PREFERRED 234 }; 235 236 PollingLoopState mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 237 238 // Runnable to return to an IDLE_STATE and reset preferred service. This should be run after we 239 // have left a field and gone a period of time without any HCE or polling frame data. 240 Runnable mReturnToIdleStateRunnable = new Runnable() { 241 @Override 242 public void run() { 243 synchronized (mLock) { 244 Log.d(TAG, "Have been outside field, returning to idle state"); 245 returnToIdleStateLocked(); 246 } 247 } 248 }; 249 250 Runnable mUnbindInactiveServicesRunnable = 251 new Runnable() { 252 @Override 253 public void run() { 254 synchronized (mLock) { 255 if (isHostCardEmulationActivated()) { 256 // Skip in active state 257 rescheduleInactivityChecks(); 258 } else { 259 unbindInactiveServicesLocked(); 260 } 261 } 262 } 263 264 void unbindInactiveServicesLocked() { 265 ComponentNameAndUser preferredNameAndUser = mAidCache.getPreferredService(); 266 Map<ComponentNameAndUser, HostEmulationConnection> retainedConnections = 267 new HashMap<>(); 268 mComponentNameToConnectionsMap.keySet().forEach((key) -> { 269 if (!preferredNameAndUser.equals(key)) { 270 HostEmulationConnection connection = 271 mComponentNameToConnectionsMap.get(key); 272 if (connection.mMessenger != null) { 273 try { 274 mContext.unbindService(connection.mServiceConnection); 275 } catch (IllegalArgumentException iae) { 276 Log.wtf(TAG, 277 "unbindInactiveServicesLocked: " 278 + "Exception while unbinding " 279 + key.getComponentName() 280 + " service connection", 281 iae); 282 } 283 } 284 } else { 285 retainedConnections.put(key, mComponentNameToConnectionsMap.get(key)); 286 } 287 }); 288 mComponentNameToConnectionsMap = retainedConnections; 289 } 290 }; 291 292 // Runnable to re-enable observe mode after a transaction. This should be delayed after 293 // HCE is deactivated to ensure we don't receive another select AID. 294 Runnable mEnableObserveModeAfterTransactionRunnable = new Runnable() { 295 @Override 296 public void run() { 297 synchronized (mLock) { 298 Log.d(TAG, "mEnableObserveModeAfterTransactionRunnable.run"); 299 if (!mEnableObserveModeAfterTransaction && !mEnableObserveModeOnFieldOff) { 300 return; 301 } 302 mEnableObserveModeAfterTransaction = false; 303 mEnableObserveModeOnFieldOff = false; 304 } 305 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 306 if (adapter == null) { 307 Log.e(TAG, "mEnableObserveModeAfterTransactionRunnable.run: " 308 + "adapter is null, returning"); 309 return; 310 } 311 adapter.setObserveModeEnabled(true); 312 } 313 }; 314 HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, NfcInjector nfcInjector)315 public HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, 316 NfcInjector nfcInjector) { 317 this(context, looper, aidCache, nfcInjector.getStatsdUtilsContext() != null ? 318 new StatsdUtils(StatsdUtils.SE_NAME_HCE, nfcInjector.getStatsdUtilsContext()) : null, 319 nfcInjector); 320 } 321 322 @VisibleForTesting HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, StatsdUtils statsdUtils, NfcInjector nfcInjector)323 HostEmulationManager(Context context, Looper looper, RegisteredAidCache aidCache, 324 StatsdUtils statsdUtils, NfcInjector nfcInjector) { 325 mContext = context; 326 mLooper = looper; 327 mHandler = new Handler(looper); 328 mLock = new Object(); 329 mAidCache = aidCache; 330 mState = STATE_IDLE; 331 mPollingLoopState = PollingLoopState.EVALUATING_POLLING_LOOP; 332 mKeyguard = context.getSystemService(KeyguardManager.class); 333 mPowerManager = context.getSystemService(PowerManager.class); 334 mStatsdUtils = Flags.statsdCeEventsFlag() ? statsdUtils : null; 335 mPollingLoopFilters = new HashMap<Integer, Map<String, List<ApduServiceInfo>>>(); 336 mPollingLoopPatternFilters = new HashMap<Integer, Map<Pattern, List<ApduServiceInfo>>>(); 337 mDeviceConfig = nfcInjector.getDeviceConfigFacade(); 338 339 if (isMultipleBindingSupported()) { 340 mHandler.postDelayed(mUnbindInactiveServicesRunnable, UNBIND_SERVICES_DELAY_MS); 341 } 342 } 343 setOemExtension(@ullable INfcOemExtensionCallback nfcOemExtensionCallback)344 public void setOemExtension(@Nullable INfcOemExtensionCallback nfcOemExtensionCallback) { 345 mNfcOemExtensionCallback = nfcOemExtensionCallback; 346 } 347 onBootCompleted()348 public void onBootCompleted() { 349 if (!mPaymentServiceBound) { 350 ComponentNameAndUser preferredPaymentService = mAidCache.getPreferredPaymentService(); 351 // getPreferredPaymentService returns a non-null object even if there is no role holder, 352 // check for package name explicitly. 353 ComponentName preferredPaymentServiceName = preferredPaymentService.getComponentName(); 354 if (preferredPaymentServiceName != null) { 355 Log.d(TAG, "onBootCompleted, payment service not bound, binding"); 356 onPreferredPaymentServiceChanged(preferredPaymentService); 357 } 358 } 359 } 360 361 /** 362 * Preferred payment service changed 363 */ onPreferredPaymentServiceChanged(final ComponentNameAndUser service)364 public void onPreferredPaymentServiceChanged(final ComponentNameAndUser service) { 365 mHandler.post(() -> { 366 synchronized (mLock) { 367 if (!isHostCardEmulationActivated()) { 368 Log.d(TAG, "onPreferredPaymentServiceChanged: resetting active service"); 369 resetActiveService(); 370 } 371 372 if (service != null && service.getComponentName() != null) { 373 bindPaymentServiceLocked(service.getUserId(), service.getComponentName()); 374 } else { 375 unbindPaymentServiceLocked(); 376 } 377 } 378 }); 379 } 380 getForegroundServiceOrDefault()381 private Messenger getForegroundServiceOrDefault() { 382 Pair<Messenger, ComponentName> pair = getForegroundServiceAndNameOrDefault(); 383 if (pair == null) { 384 return null; 385 } 386 return pair.first; 387 } 388 getForegroundServiceAndNameOrDefault()389 private Pair<Messenger, ComponentName> getForegroundServiceAndNameOrDefault() { 390 ComponentNameAndUser preferredService = mAidCache.getPreferredService(); 391 int preferredServiceUserId = preferredService.getUserId(); 392 ComponentName preferredServiceName = preferredService.getComponentName(); 393 394 if (preferredServiceName == null || preferredServiceUserId < 0) { 395 return null; 396 } 397 398 return new Pair<>(bindServiceIfNeededLocked(preferredServiceUserId, preferredServiceName), 399 preferredServiceName); 400 } 401 402 403 @TargetApi(35) updateForShouldDefaultToObserveMode(boolean enabled)404 public void updateForShouldDefaultToObserveMode(boolean enabled) { 405 synchronized (mLock) { 406 if (isHostCardEmulationActivated()) { 407 mEnableObserveModeAfterTransaction = enabled; 408 return; 409 } 410 if (mHandler.hasCallbacks(mEnableObserveModeAfterTransactionRunnable)) { 411 if (enabled) { 412 return; 413 } else { 414 mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable); 415 } 416 } 417 mEnableObserveModeAfterTransaction = false; 418 mEnableObserveModeOnFieldOff = false; 419 } 420 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 421 adapter.setObserveModeEnabled(enabled); 422 } 423 424 425 @TargetApi(35) updatePollingLoopFilters(@serIdInt int userId, List<ApduServiceInfo> services)426 public void updatePollingLoopFilters(@UserIdInt int userId, List<ApduServiceInfo> services) { 427 HashMap<String, List<ApduServiceInfo>> pollingLoopFilters = 428 new HashMap<String, List<ApduServiceInfo>>(); 429 HashMap<Pattern, List<ApduServiceInfo>> pollingLoopPatternFilters = 430 new HashMap<Pattern, List<ApduServiceInfo>>(); 431 for (ApduServiceInfo serviceInfo : services) { 432 for (String plf : serviceInfo.getPollingLoopFilters()) { 433 List<ApduServiceInfo> list = 434 pollingLoopFilters.getOrDefault(plf, new ArrayList<ApduServiceInfo>()); 435 list.add(serviceInfo); 436 pollingLoopFilters.putIfAbsent(plf, list); 437 438 } 439 for (Pattern plpf : serviceInfo.getPollingLoopPatternFilters()) { 440 List<ApduServiceInfo> list = 441 pollingLoopPatternFilters.getOrDefault(plpf, 442 new ArrayList<ApduServiceInfo>()); 443 list.add(serviceInfo); 444 pollingLoopPatternFilters.putIfAbsent(plpf, list); 445 446 } 447 } 448 mPollingLoopFilters.put(Integer.valueOf(userId), pollingLoopFilters); 449 mPollingLoopPatternFilters.put(Integer.valueOf(userId), pollingLoopPatternFilters); 450 } 451 onObserveModeStateChange(boolean enabled)452 public void onObserveModeStateChange(boolean enabled) { 453 synchronized(mLock) { 454 if (!enabled && mAutoDisableObserveModeRunnable != null) { 455 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable); 456 mAutoDisableObserveModeRunnable = null; 457 } 458 } 459 } 460 461 class AutoDisableObserveModeRunnable implements Runnable { 462 Set<String> mServicePackageNames; AutoDisableObserveModeRunnable(ComponentName componentName)463 AutoDisableObserveModeRunnable(ComponentName componentName) { 464 mServicePackageNames = new ArraySet<>(1); 465 addServiceToList(componentName); 466 } 467 468 @Override run()469 public void run() { 470 synchronized(mLock) { 471 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 472 if (!adapter.isObserveModeEnabled()) { 473 return; 474 } 475 if (arePackagesInForeground()) { 476 return; 477 } 478 Log.w(TAG, 479 "AutoDisableObserveModeRunnable: Observe mode not disabled and " 480 + "no application from the following " 481 + "packages are in the foreground: " 482 + String.join(", ", mServicePackageNames)); 483 allowOneTransaction(); 484 } 485 } 486 487 addServiceToList(ComponentName service)488 void addServiceToList(ComponentName service) { 489 mServicePackageNames.add(service.getPackageName()); 490 } 491 arePackagesInForeground()492 boolean arePackagesInForeground() { 493 ActivityManager am = mContext.getSystemService(ActivityManager.class); 494 if (am == null) { 495 return false; 496 } 497 ForegroundUtils foregroundUtils = ForegroundUtils.getInstance(am); 498 if (foregroundUtils == null) { 499 return false; 500 } 501 PackageManager packageManager = mContext.getPackageManager(); 502 if (packageManager == null) { 503 return false; 504 } 505 List<Integer> uids = foregroundUtils.getForegroundUids(); 506 if (uids != null && mServicePackageNames != null) { 507 for (Integer uid : uids) { 508 String[] packageNames = packageManager.getPackagesForUid(uid); 509 if (packageNames != null) { 510 for (String packageName : packageNames) { 511 if (packageName != null) { 512 for (String servicePackageName : mServicePackageNames) { 513 if (Objects.equals(servicePackageName, packageName)) { 514 return true; 515 } 516 } 517 } 518 } 519 } 520 } 521 } 522 return false; 523 } 524 } 525 sendFrameToServiceLocked(Messenger service, ComponentName name, PollingFrame frame)526 private void sendFrameToServiceLocked(Messenger service, ComponentName name, 527 PollingFrame frame) { 528 sendFramesToServiceLocked(service, name, Arrays.asList(frame)); 529 } 530 sendFramesToServiceLocked(Messenger service, ComponentName name, List<PollingFrame> frames)531 private void sendFramesToServiceLocked(Messenger service, ComponentName name, 532 List<PollingFrame> frames) { 533 if (service != null) { 534 sendPollingFramesToServiceLocked(service, new ArrayList<>(frames)); 535 } else { 536 mUnprocessedPollingFrames = new ArrayList<PollingFrame>(); 537 if (mPollingFramesToSend == null) { 538 mPollingFramesToSend = new HashMap<ComponentName, ArrayList<PollingFrame>>(); 539 } 540 if (mPollingFramesToSend.containsKey(name)) { 541 mPollingFramesToSend.get(name).addAll(frames); 542 } else { 543 mPollingFramesToSend.put(name, new ArrayList<>(frames)); 544 } 545 } 546 if (Flags.autoDisableObserveMode()) { 547 if (mAutoDisableObserveModeRunnable == null) { 548 mAutoDisableObserveModeRunnable = new AutoDisableObserveModeRunnable(name); 549 mHandler.postDelayed(mAutoDisableObserveModeRunnable, 3000); 550 } else { 551 mAutoDisableObserveModeRunnable.addServiceToList(name); 552 } 553 } 554 } 555 rescheduleInactivityChecks()556 void rescheduleInactivityChecks() { 557 mHandler.removeCallbacks(mReturnToIdleStateRunnable); 558 if (isMultipleBindingSupported()) { 559 mHandler.removeCallbacks(mUnbindInactiveServicesRunnable); 560 mHandler.postDelayed(mUnbindInactiveServicesRunnable, UNBIND_SERVICES_DELAY_MS); 561 } 562 } 563 setPollingLoopStateLocked(PollingLoopState state)564 private void setPollingLoopStateLocked(PollingLoopState state) { 565 Log.d(TAG, "setPollingLoopStateLocked: " + mPollingLoopState + " -> " + state); 566 mPollingLoopState = state; 567 } 568 569 @TargetApi(35) onPollingLoopDetected(List<PollingFrame> pollingFrames)570 public void onPollingLoopDetected(List<PollingFrame> pollingFrames) { 571 Log.d(TAG, "onPollingLoopDetected: size: " + pollingFrames.size()); 572 synchronized (mLock) { 573 rescheduleInactivityChecks(); 574 // We need to have this check here in addition to the one in onFieldChangeDetected, 575 // because we can receive an OFF frame after the field change is detected. 576 if (!pollingFrames.isEmpty() 577 && pollingFrames.getLast().getType() == PollingFrame.POLLING_LOOP_TYPE_OFF) { 578 mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS); 579 } 580 581 if (mState == STATE_IDLE) { 582 mState = STATE_POLLING_LOOP; 583 } 584 int onCount = 0; 585 int offCount = 0; 586 int aCount = 0; 587 int bCount = 0; 588 if (mPendingPollingLoopFrames == null) { 589 mPendingPollingLoopFrames = new ArrayList<PollingFrame>(1); 590 } 591 for (PollingFrame pollingFrame : pollingFrames) { 592 if (mUnprocessedPollingFrames != null) { 593 mUnprocessedPollingFrames.add(pollingFrame); 594 } else if (pollingFrame.getType() 595 == PollingFrame.POLLING_LOOP_TYPE_F) { 596 Pair<Messenger, ComponentName> serviceAndName = 597 getForegroundServiceAndNameOrDefault(); 598 if (serviceAndName != null) { 599 sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second, 600 pollingFrame); 601 } 602 } else if (pollingFrame.getType() 603 == PollingFrame.POLLING_LOOP_TYPE_UNKNOWN) { 604 byte[] data = pollingFrame.getData(); 605 String dataStr = HexFormat.of().formatHex(data).toUpperCase(Locale.ROOT); 606 List<ApduServiceInfo> serviceInfos = 607 mPollingLoopFilters.get(ActivityManager.getCurrentUser()).get(dataStr); 608 Map<Pattern, List<ApduServiceInfo>> patternMappingForUser = 609 mPollingLoopPatternFilters.get(ActivityManager.getCurrentUser()); 610 Set<Pattern> patternSet = patternMappingForUser.keySet(); 611 List<Pattern> matchedPatterns = patternSet.stream() 612 .filter(p -> p.matcher(dataStr).matches()).toList(); 613 if (!matchedPatterns.isEmpty()) { 614 if (serviceInfos == null) { 615 serviceInfos = new ArrayList<ApduServiceInfo>(); 616 } 617 for (Pattern matchedPattern : matchedPatterns) { 618 serviceInfos.addAll(patternMappingForUser.get(matchedPattern)); 619 } 620 } 621 if (serviceInfos != null && serviceInfos.size() > 0) { 622 ApduServiceInfo serviceInfo; 623 if (serviceInfos.size() == 1) { 624 serviceInfo = serviceInfos.get(0); 625 } else { 626 serviceInfo = mAidCache.resolvePollingLoopFilterConflict(serviceInfos); 627 if (serviceInfo == null) { 628 /* If neither the foreground or payments service can handle the plf, 629 * pick the first in the list. */ 630 serviceInfo = serviceInfos.get(0); 631 } 632 } 633 if (serviceInfo.getShouldAutoTransact(dataStr)) { 634 if (mStatsdUtils != null) { 635 mStatsdUtils.logAutoTransactReported( 636 StatsdUtils.PROCESSOR_HOST, data); 637 mStatsdUtils.setNextObserveModeTriggerSource( 638 StatsdUtils.TRIGGER_SOURCE_AUTO_TRANSACT); 639 } 640 if (mFirmwareExitFrame != null && Arrays.equals( 641 mFirmwareExitFrame.getData(), pollingFrame.getData())) { 642 mFirmwareExitFrame = null; 643 mEnableObserveModeAfterTransaction = true; 644 Log.d(TAG, 645 "Polling frame matches exit frame, leaving observe mode " 646 + "disabled"); 647 } else { 648 allowOneTransaction(); 649 } 650 pollingFrame.setTriggeredAutoTransact(true); 651 } 652 UserHandle user = UserHandle.getUserHandleForUid(serviceInfo.getUid()); 653 if (serviceInfo.isOnHost()) { 654 Messenger service = bindServiceIfNeededLocked(user.getIdentifier(), 655 serviceInfo.getComponent()); 656 setPollingLoopStateLocked(PollingLoopState.FILTER_MATCHED); 657 sendFrameToServiceLocked(service, serviceInfo.getComponent(), 658 pollingFrame); 659 } 660 } else { 661 Pair<Messenger, ComponentName> serviceAndName = 662 getForegroundServiceAndNameOrDefault(); 663 if (serviceAndName != null) { 664 sendFrameToServiceLocked(serviceAndName.first, serviceAndName.second, 665 pollingFrame); 666 } 667 } 668 669 if (mStatsdUtils != null) { 670 mStatsdUtils.tallyPollingFrame(dataStr, pollingFrame); 671 } 672 } else { 673 mPendingPollingLoopFrames.add(pollingFrame); 674 } 675 if (mStatsdUtils != null) { 676 mStatsdUtils.logPollingFrames(); 677 } 678 } 679 mFirmwareExitFrame = null; 680 681 if (mPollingLoopState == PollingLoopState.EVALUATING_POLLING_LOOP) { 682 if (mPendingPollingLoopFrames.size() >= 3) { 683 for (PollingFrame frame : mPendingPollingLoopFrames) { 684 int type = frame.getType(); 685 switch (type) { 686 case PollingFrame.POLLING_LOOP_TYPE_A: 687 aCount++; 688 if (aCount > 3) { 689 setPollingLoopStateLocked( 690 PollingLoopState.DELIVERING_TO_PREFERRED); 691 } 692 break; 693 case PollingFrame.POLLING_LOOP_TYPE_B: 694 bCount++; 695 if (bCount > 3) { 696 setPollingLoopStateLocked( 697 PollingLoopState.DELIVERING_TO_PREFERRED); 698 } 699 break; 700 case PollingFrame.POLLING_LOOP_TYPE_ON: 701 onCount++; 702 break; 703 case PollingFrame.POLLING_LOOP_TYPE_OFF: 704 // Send the loop data if we've seen at least one on before an off. 705 offCount++; 706 if (onCount >= 2 && offCount >=2) { 707 setPollingLoopStateLocked( 708 PollingLoopState.DELIVERING_TO_PREFERRED); 709 } 710 break; 711 default: 712 } 713 if (mPollingLoopState != PollingLoopState.EVALUATING_POLLING_LOOP) { 714 break; 715 } 716 } 717 } 718 } 719 720 if (mPollingLoopState == PollingLoopState.DELIVERING_TO_PREFERRED) { 721 Pair<Messenger, ComponentName> serviceAndName = 722 getForegroundServiceAndNameOrDefault(); 723 if (serviceAndName != null) { 724 sendFramesToServiceLocked(serviceAndName.first, serviceAndName.second, 725 mPendingPollingLoopFrames); 726 mPendingPollingLoopFrames = null; 727 } else { 728 Log.i(TAG, "onPollingLoopDetected: No preferred service to deliver " 729 + "polling frames to, allowing transaction"); 730 allowOneTransaction(); 731 } 732 } 733 } 734 } 735 allowOneTransaction()736 private void allowOneTransaction() { 737 Log.d(TAG, "allowOneTransaction"); 738 mEnableObserveModeAfterTransaction = true; 739 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext); 740 mHandler.post(() -> adapter.setObserveModeEnabled(false)); 741 } 742 743 /** 744 * Observe mode was disabled in firmware, we shouldn't autotransact on the next frame. 745 * 746 * This assumes the exit frame will be in the next batch of processed polling frames. 747 */ onObserveModeDisabledInFirmware(PollingFrame exitFrame)748 public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) { 749 mFirmwareExitFrame = exitFrame; 750 } 751 752 /** 753 * Preferred foreground service changed 754 */ onPreferredForegroundServiceChanged(ComponentNameAndUser serviceAndUser)755 public void onPreferredForegroundServiceChanged(ComponentNameAndUser serviceAndUser) { 756 synchronized (mLock) { 757 int userId = serviceAndUser.getUserId(); 758 ComponentName service = serviceAndUser.getComponentName(); 759 760 mAidCache.onPreferredForegroundServiceChanged(serviceAndUser); 761 762 if (!isHostCardEmulationActivated()) { 763 Log.d(TAG, "onPreferredForegroundServiceChanged: resetting active service"); 764 resetActiveService(); 765 } 766 if (service != null) { 767 bindServiceIfNeededLocked(userId, service); 768 } else { 769 unbindServiceIfNeededLocked(); 770 } 771 } 772 } 773 onFieldChangeDetected(boolean fieldOn)774 public void onFieldChangeDetected(boolean fieldOn) { 775 rescheduleInactivityChecks(); 776 if (!fieldOn) { 777 mHandler.postDelayed(mReturnToIdleStateRunnable, FIELD_OFF_IDLE_DELAY_MS); 778 } 779 if (!fieldOn && mEnableObserveModeOnFieldOff && mEnableObserveModeAfterTransaction) { 780 Log.d(TAG, "onFieldChangeDetected: re-enable observe mode"); 781 mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable, 782 RE_ENABLE_OBSERVE_MODE_DELAY_MS); 783 } 784 785 if (fieldOn && nfcHceLatencyEvents()) { 786 mFieldOnTime = SystemClock.elapsedRealtime(); 787 } 788 } 789 onHostEmulationActivated()790 public void onHostEmulationActivated() { 791 Log.d(TAG, "onHostEmulationActivated"); 792 synchronized (mLock) { 793 if (nfcHceLatencyEvents()) { 794 Trace.beginAsyncSection(EVENT_HCE_ACTIVATED, 0); 795 } 796 rescheduleInactivityChecks(); 797 // Regardless of what happens, if we're having a tap again 798 // activity up, close it 799 Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE); 800 intent.setPackage(NfcInjector.getInstance().getNfcPackageName()); 801 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 802 if (mState != STATE_IDLE && mState != STATE_POLLING_LOOP) { 803 Log.e(TAG, "onHostEmulationActivated: Got activation event in non-idle state"); 804 } 805 mState = STATE_W4_SELECT; 806 } 807 } 808 809 static private class UnroutableAidBugReportRunnable implements Runnable { 810 List<String> mUnroutedAids; 811 UnroutableAidBugReportRunnable(String aid)812 UnroutableAidBugReportRunnable(String aid) { 813 mUnroutedAids = new ArrayList<String>(1); 814 mUnroutedAids.add(aid); 815 } 816 addAid(String aid)817 void addAid(String aid) { 818 mUnroutedAids.add(aid); 819 } 820 @Override run()821 public void run() { 822 NfcService.getInstance().mNfcDiagnostics.takeBugReport( 823 "NFC tap failed." 824 + " (If you weren't using NFC, " 825 + "no need to submit this report.)", 826 "Couldn't route " + String.join(", ", mUnroutedAids)); 827 } 828 } 829 830 UnroutableAidBugReportRunnable mUnroutableAidBugReportRunnable = null; 831 onHostEmulationData(byte[] data)832 public void onHostEmulationData(byte[] data) { 833 Log.d(TAG, "onHostEmulationData"); 834 mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable); 835 rescheduleInactivityChecks(); 836 String selectAid = findSelectAid(data); 837 ComponentName resolvedService = null; 838 ApduServiceInfo resolvedServiceInfo = null; 839 AidResolveInfo resolveInfo = null; 840 synchronized (mLock) { 841 if (mState == STATE_IDLE) { 842 Log.e(TAG, "onHostEmulationData: Got data in idle state."); 843 return; 844 } else if (mState == STATE_W4_DEACTIVATE) { 845 Log.e(TAG, "onHostEmulationData: Dropping APDU in STATE_W4_DECTIVATE"); 846 return; 847 } 848 if (selectAid != null) { 849 if (selectAid.equals(ANDROID_HCE_AID)) { 850 NfcService.getInstance().sendData(ANDROID_HCE_RESPONSE); 851 return; 852 } 853 resolveInfo = mAidCache.resolveAid(selectAid); 854 if (resolveInfo == null || resolveInfo.services.size() == 0) { 855 if (selectAid.equals(NDEF_V1_AID) || selectAid.equals(NDEF_V2_AID)) { 856 Log.w(TAG, 857 "onHostEmulationData: Can't route NDEF AID, sending AID_NOT_FOUND"); 858 } else if (!mPowerManager.isScreenOn()) { 859 Log.i(TAG, 860 "onHostEmulationData: Screen is off, sending AID_NOT_FOUND, " 861 + "but not triggering bug report"); 862 } else { 863 Log.w(TAG, "onHostEmulationData: Can't handle AID " + selectAid 864 + " sending AID_NOT_FOUND"); 865 if (android.nfc.Flags.nfcEventListener()) { 866 notifyAidNotRoutedListener(selectAid); 867 } 868 if (mUnroutableAidBugReportRunnable != null) { 869 mUnroutableAidBugReportRunnable.addAid(selectAid); 870 } else { 871 mUnroutableAidBugReportRunnable = 872 new UnroutableAidBugReportRunnable(selectAid); 873 /* Wait 1s to see if there is an alternate AID we can route before 874 * taking a bug report */ 875 mHandler.postDelayed(mUnroutableAidBugReportRunnable, 1000); 876 } 877 } 878 NfcInjector.getInstance().getNfcEventLog().logEvent( 879 NfcEventProto.EventType.newBuilder() 880 .setCeUnroutableAid( 881 NfcEventProto.NfcCeUnroutableAid.newBuilder() 882 .setAid(selectAid) 883 .build()) 884 .build()); 885 // Tell the remote we don't handle this AID 886 NfcService.getInstance().sendData(AID_NOT_FOUND); 887 return; 888 } else if (mUnroutableAidBugReportRunnable != null) { 889 /* If there is a pending bug report runnable, cancel it. */ 890 mHandler.removeCallbacks(mUnroutableAidBugReportRunnable); 891 mUnroutableAidBugReportRunnable = null; 892 } 893 mLastSelectedAid = selectAid; 894 if (resolveInfo.defaultService != null) { 895 // Resolve to default 896 // Check if resolvedService requires unlock 897 ApduServiceInfo defaultServiceInfo = resolveInfo.defaultService; 898 if (mStatsdUtils != null) { 899 mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category); 900 mStatsdUtils.setCardEmulationEventUid(defaultServiceInfo.getUid()); 901 } 902 if ((defaultServiceInfo.requiresUnlock() 903 || NfcService.getInstance().isSecureNfcEnabled()) 904 && NfcInjector.getInstance().isDeviceLocked()) { 905 NfcService.getInstance().sendRequireUnlockIntent(); 906 NfcService.getInstance().sendData(AID_NOT_FOUND); 907 if (DBG) Log.d(TAG, "onHostEmulationData: requiresUnlock()! show toast"); 908 if (mStatsdUtils != null) { 909 mStatsdUtils.logCardEmulationWrongSettingEvent(); 910 } 911 launchTapAgain(resolveInfo.defaultService, resolveInfo.category); 912 return; 913 } 914 if (defaultServiceInfo.requiresScreenOn() && !mPowerManager.isScreenOn()) { 915 NfcService.getInstance().sendData(AID_NOT_FOUND); 916 if (DBG) Log.d(TAG, "onHostEmulationData: requiresScreenOn()!"); 917 if (mStatsdUtils != null) { 918 mStatsdUtils.logCardEmulationWrongSettingEvent(); 919 } 920 return; 921 } 922 // In no circumstance should this be an OffHostService - 923 // we should never get this AID on the host in the first place 924 if (!defaultServiceInfo.isOnHost()) { 925 Log.e(TAG, "onHostEmulationData: AID that was meant to go off-host was " 926 + "routed to host. Check routing table configuration."); 927 NfcService.getInstance().sendData(AID_NOT_FOUND); 928 if (mStatsdUtils != null) { 929 mStatsdUtils.logCardEmulationNoRoutingEvent(); 930 } 931 return; 932 } 933 resolvedService = defaultServiceInfo.getComponent(); 934 resolvedServiceInfo = defaultServiceInfo; 935 } else if (mActiveServiceName != null) { 936 for (ApduServiceInfo serviceInfo : resolveInfo.services) { 937 if (mActiveServiceName.equals(serviceInfo.getComponent())) { 938 resolvedService = mActiveServiceName; 939 resolvedServiceInfo = serviceInfo; 940 break; 941 } 942 } 943 } 944 if (resolvedService == null) { 945 // We have no default, and either one or more services. 946 // Ask the user to confirm. 947 // Just ignore all future APDUs until we resolve to only one 948 mState = STATE_W4_DEACTIVATE; 949 NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, selectAid); 950 if (android.nfc.Flags.nfcEventListener()) { 951 notifyAidConflictListener(selectAid); 952 } 953 if (mStatsdUtils != null) { 954 mStatsdUtils.setCardEmulationEventCategory(CardEmulation.CATEGORY_OTHER); 955 mStatsdUtils.logCardEmulationWrongSettingEvent(); 956 } 957 launchResolver(selectAid, (ArrayList<ApduServiceInfo>)resolveInfo.services, 958 null, resolveInfo.category); 959 return; 960 } 961 } 962 switch (mState) { 963 case STATE_W4_SELECT: 964 if (selectAid != null) { 965 int uid = resolvedServiceInfo.getUid(); 966 if (mStatsdUtils != null) { 967 mStatsdUtils.setCardEmulationEventUid(uid); 968 mStatsdUtils.setCardEmulationEventCategory(resolveInfo.category); 969 } 970 UserHandle user = 971 UserHandle.getUserHandleForUid(uid); 972 Messenger existingService = 973 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService); 974 if (existingService != null) { 975 Log.d(TAG, "onHostEmulationData: Send data to existing service"); 976 NfcInjector.getInstance().getNfcEventLog().logEvent( 977 NfcEventProto.EventType.newBuilder() 978 .setCeRoutedAid( 979 NfcEventProto.NfcCeRoutedAid.newBuilder() 980 .setAid(selectAid) 981 .setComponentInfo( 982 NfcEventProto.NfcComponentInfo.newBuilder() 983 .setPackageName( 984 resolvedService.getPackageName()) 985 .setClassName( 986 resolvedService.getClassName()) 987 .build()) 988 .build()) 989 .build()); 990 sendDataToServiceLocked(existingService, data); 991 } else { 992 // Waiting for service to be bound 993 Log.d(TAG, "onHostEmulationData: Waiting for new service."); 994 // Queue SELECT APDU to be used 995 mSelectApdu = data; 996 mState = STATE_W4_SERVICE; 997 } 998 if (mStatsdUtils != null) { 999 mStatsdUtils.notifyCardEmulationEventWaitingForResponse(); 1000 } else { 1001 int statsdCategory = 1002 resolveInfo.category.equals(CardEmulation.CATEGORY_PAYMENT) 1003 ? CE_HCE_PAYMENT 1004 : CE_HCE_OTHER; 1005 NfcStatsLog.write( 1006 NfcStatsLog.NFC_CARDEMULATION_OCCURRED, 1007 statsdCategory, 1008 "HCE", 1009 uid); 1010 } 1011 } else { 1012 Log.d(TAG, "onHostEmulationData: Dropping non-select APDU " 1013 + "in STATE_W4_SELECT"); 1014 NfcService.getInstance().sendData(UNKNOWN_ERROR); 1015 } 1016 break; 1017 case STATE_W4_SERVICE: 1018 Log.d(TAG, "onHostEmulationData: Unexpected APDU in STATE_W4_SERVICE"); 1019 break; 1020 case STATE_XFER: 1021 if (selectAid != null) { 1022 UserHandle user = 1023 UserHandle.getUserHandleForUid(resolvedServiceInfo.getUid()); 1024 Messenger existingService = 1025 bindServiceIfNeededLocked(user.getIdentifier(), resolvedService); 1026 if (existingService != null) { 1027 sendDataToServiceLocked(existingService, data); 1028 } else { 1029 // Waiting for service to be bound 1030 mSelectApdu = data; 1031 mState = STATE_W4_SERVICE; 1032 } 1033 } else if (mActiveService != null) { 1034 // Regular APDU data 1035 sendDataToServiceLocked(mActiveService, data); 1036 } else { 1037 // No SELECT AID and no active service. 1038 Log.d(TAG, "onHostEmulationData: Service no longer bound, dropping APDU"); 1039 } 1040 break; 1041 } 1042 } 1043 } 1044 onHostEmulationDeactivated()1045 public void onHostEmulationDeactivated() { 1046 Log.d(TAG, "onHostEmulationDeactivated"); 1047 synchronized (mLock) { 1048 if (mState == STATE_IDLE) { 1049 Log.e(TAG, "onHostEmulationDeactivated: Got deactivation " 1050 + "event while in idle state"); 1051 } 1052 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_LINK_LOSS); 1053 unbindServiceIfNeededLocked(); 1054 returnToIdleStateLocked(); 1055 1056 if (mAutoDisableObserveModeRunnable != null) { 1057 mHandler.removeCallbacks(mAutoDisableObserveModeRunnable); 1058 mAutoDisableObserveModeRunnable = null; 1059 } 1060 1061 if (mEnableObserveModeAfterTransaction) { 1062 Log.d(TAG, "onHostEmulationDeactivated: re-enable observe mode."); 1063 mHandler.postDelayed(mEnableObserveModeAfterTransactionRunnable, 1064 RE_ENABLE_OBSERVE_MODE_DELAY_MS); 1065 } 1066 1067 if (mStatsdUtils != null) { 1068 mStatsdUtils.logCardEmulationDeactivatedEvent(); 1069 } 1070 1071 if (nfcHceLatencyEvents()) { 1072 Trace.endAsyncSection(EVENT_HCE_ACTIVATED, 0); 1073 1074 long endTime = SystemClock.elapsedRealtime(); 1075 long tapDuration = endTime - mFieldOnTime; 1076 if (tapDuration > mDeviceConfig.getSlowTapThresholdMillis()) { 1077 PerfettoTrigger.trigger(TRIGGER_NAME_SLOW_TAP); 1078 } 1079 } 1080 } 1081 } 1082 isHostCardEmulationActivated()1083 public boolean isHostCardEmulationActivated() { 1084 synchronized (mLock) { 1085 return mState != STATE_IDLE && mState != STATE_POLLING_LOOP; 1086 } 1087 } 1088 onOffHostAidSelected()1089 public void onOffHostAidSelected() { 1090 Log.d(TAG, "onOffHostAidSelected"); 1091 synchronized (mLock) { 1092 mHandler.removeCallbacks(mEnableObserveModeAfterTransactionRunnable); 1093 rescheduleInactivityChecks(); 1094 if (mState != STATE_XFER || mActiveService == null) { 1095 // Don't bother telling, we're not bound to any service yet 1096 } else { 1097 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 1098 } 1099 if (mEnableObserveModeAfterTransaction) { 1100 Log.i(TAG, "onOffHostAidSelected: OffHost AID selected, " 1101 + "waiting for Field off to reenable observe mode"); 1102 mEnableObserveModeOnFieldOff = true; 1103 } 1104 resetActiveService(); 1105 unbindServiceIfNeededLocked(); 1106 mState = STATE_W4_SELECT; 1107 1108 //close the TapAgainDialog 1109 Intent intent = new Intent(TapAgainDialog.ACTION_CLOSE); 1110 intent.setPackage(NfcInjector.getInstance().getNfcPackageName()); 1111 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1112 } 1113 } 1114 bindServiceIfNeededLocked(@serIdInt int userId, ComponentName service)1115 Messenger bindServiceIfNeededLocked(@UserIdInt int userId, ComponentName service) { 1116 if (service == null) { 1117 Log.e(TAG, "bindServiceIfNeededLocked: service ComponentName is null"); 1118 return null; 1119 } 1120 1121 ComponentNameAndUser preferredPaymentService = mAidCache.getPreferredPaymentService(); 1122 int preferredPaymentUserId = preferredPaymentService.getUserId(); 1123 ComponentName preferredPaymentServiceName = preferredPaymentService.getComponentName(); 1124 ComponentNameAndUser newServiceAndUser = new ComponentNameAndUser(userId, service); 1125 1126 if (mPaymentServiceName != null && mPaymentServiceName.equals(service) 1127 && mPaymentServiceUserId == userId) { 1128 Log.d(TAG, "bindServiceIfNeededLocked: Service already bound as payment service."); 1129 return mPaymentService; 1130 } else if (!mPaymentServiceBound && preferredPaymentServiceName != null 1131 && preferredPaymentServiceName.equals(service) 1132 && preferredPaymentUserId == userId) { 1133 Log.d(TAG, "bindServiceIfNeededLocked: Service should be bound as " 1134 + "payment service but is not, binding now"); 1135 bindPaymentServiceLocked(userId, preferredPaymentServiceName); 1136 return null; 1137 } else if (!isMultipleBindingSupported() 1138 && mServiceName != null 1139 && mServiceName.equals(service) 1140 && mServiceUserId == userId) { 1141 Log.d(TAG, "bindServiceIfNeededLocked: Service already bound as regular service."); 1142 return mService; 1143 } else if (isMultipleBindingSupported() 1144 && mComponentNameToConnectionsMap.containsKey(newServiceAndUser) 1145 && mComponentNameToConnectionsMap.get(newServiceAndUser).mMessenger != null) { 1146 Log.d(TAG, "bindServiceIfNeededLocked: Service" + service 1147 + " already bound as regular service."); 1148 return mComponentNameToConnectionsMap.get(newServiceAndUser).mMessenger; 1149 } else { 1150 Log.d(TAG, "bindServiceIfNeededLocked: Binding to service " + service + " for userId:" 1151 + userId); 1152 if (nfcHceLatencyEvents()) { 1153 Trace.beginAsyncSection(EVENT_HCE_BIND_SERVICE, 0); 1154 } 1155 if (mStatsdUtils != null) { 1156 mStatsdUtils.notifyCardEmulationEventWaitingForService(); 1157 } 1158 unbindServiceIfNeededLocked(); 1159 Intent aidIntent = new Intent(HostApduService.SERVICE_INTERFACE); 1160 aidIntent.setComponent(service); 1161 try { 1162 ServiceConnection connection = mConnection; 1163 if (isMultipleBindingSupported()) { 1164 connection = new HostEmulationServiceConnection(userId); 1165 mComponentNameToConnectionsMap.put( 1166 new ComponentNameAndUser(userId, service), 1167 new HostEmulationConnection(userId, service, connection)); 1168 } 1169 boolean serviceBound = 1170 mContext.bindServiceAsUser( 1171 aidIntent, 1172 connection, 1173 Context.BIND_AUTO_CREATE 1174 | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, 1175 UserHandle.of(userId)); 1176 if (!isMultipleBindingSupported()) { 1177 mServiceBound = serviceBound; 1178 } 1179 if (!serviceBound) { 1180 if (nfcHceLatencyEvents()) { 1181 Trace.endAsyncSection(EVENT_HCE_BIND_SERVICE, 0); 1182 } 1183 Log.e(TAG, "bindServiceIfNeededLocked: Could not bind service."); 1184 } else { 1185 mServiceUserId = userId; 1186 } 1187 } catch (SecurityException e) { 1188 if (nfcHceLatencyEvents()) { 1189 Trace.endAsyncSection(EVENT_HCE_BIND_SERVICE, 0); 1190 } 1191 Log.e(TAG, "bindServiceIfNeededLocked: Could not bind service " 1192 + "due to security exception."); 1193 } 1194 return null; 1195 } 1196 } 1197 generateApduAckCookie()1198 private int generateApduAckCookie() { 1199 byte[] token = new byte[Integer.BYTES]; 1200 mCookieRandom.nextBytes(token); 1201 return ByteBuffer.wrap(token).getInt(); 1202 } 1203 sendDataToServiceLocked(Messenger service, byte[] data)1204 void sendDataToServiceLocked(Messenger service, byte[] data) { 1205 mState = STATE_XFER; 1206 1207 int cookie = 0; 1208 if (nfcHceLatencyEvents()) { 1209 cookie = generateApduAckCookie(); 1210 Trace.beginAsyncSection(EVENT_HCE_COMMAND_APDU, cookie); 1211 } 1212 1213 if (!Objects.equals(service, mActiveService)) { 1214 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 1215 mActiveService = service; 1216 if (service.equals(mPaymentService)) { 1217 mActiveServiceName = mPaymentServiceName; 1218 mActiveServiceUserId = mPaymentServiceUserId; 1219 } else { 1220 if (isMultipleBindingSupported()) { 1221 for (Map.Entry<ComponentNameAndUser, HostEmulationConnection> entry : 1222 mComponentNameToConnectionsMap.entrySet()) { 1223 if (service.equals(entry.getValue().mMessenger)) { 1224 mActiveServiceName = entry.getKey().getComponentName(); 1225 mActiveServiceUserId = entry.getKey().getUserId(); 1226 break; 1227 } 1228 } 1229 } else { 1230 mActiveServiceName = mServiceName; 1231 mActiveServiceUserId = mServiceUserId; 1232 } 1233 } 1234 } 1235 Message msg = Message.obtain(null, HostApduService.MSG_COMMAND_APDU); 1236 Bundle dataBundle = new Bundle(); 1237 dataBundle.putByteArray(DATA_KEY, data); 1238 msg.setData(dataBundle); 1239 msg.replyTo = mMessenger; 1240 if (nfcHceLatencyEvents()) { 1241 msg.arg1 = cookie; 1242 } 1243 try { 1244 NfcService.getInstance().notifyOemLogEvent(new OemLogItems 1245 .Builder(OemLogItems.LOG_ACTION_HCE_DATA) 1246 .setApduCommand(data) 1247 .build()); 1248 mActiveService.send(msg); 1249 } catch (RemoteException e) { 1250 if (nfcHceLatencyEvents()) { 1251 Trace.endAsyncSection(EVENT_HCE_COMMAND_APDU, cookie); 1252 } 1253 Log.e(TAG, "sendDataToServiceLocked: Remote service " + mActiveServiceName 1254 + " has died, dropping APDU", e); 1255 if (Objects.equals(mActiveService, mPaymentService)) { 1256 Log.wtf(TAG, "sendDataToServiceLocked: Rebinding payment service", e); 1257 bindPaymentServiceLocked(mPaymentServiceUserId, mLastBoundPaymentServiceName); 1258 } 1259 } 1260 } 1261 sendPollingFramesToServiceLocked(Messenger service, ArrayList<PollingFrame> pollingFrames)1262 void sendPollingFramesToServiceLocked(Messenger service, 1263 ArrayList<PollingFrame> pollingFrames) { 1264 if (!Objects.equals(service, mActiveService)) { 1265 if (!isMultipleBindingSupported()) { 1266 sendDeactivateToActiveServiceLocked(HostApduService.DEACTIVATION_DESELECTED); 1267 } 1268 mActiveService = service; 1269 if (service.equals(mPaymentService)) { 1270 mActiveServiceName = mPaymentServiceName; 1271 mActiveServiceUserId = mPaymentServiceUserId; 1272 } else { 1273 mActiveServiceName = mServiceName; 1274 mActiveServiceUserId = mServiceUserId; 1275 } 1276 } 1277 Message msg = Message.obtain(null, HostApduService.MSG_POLLING_LOOP); 1278 Bundle msgData = new Bundle(); 1279 msgData.putParcelableArrayList(HostApduService.KEY_POLLING_LOOP_FRAMES_BUNDLE, 1280 pollingFrames); 1281 msg.setData(msgData); 1282 msg.replyTo = mMessenger; 1283 if (mState == STATE_IDLE) { 1284 mState = STATE_POLLING_LOOP; 1285 } 1286 if (nfcHceLatencyEvents()) { 1287 int cookie = generateApduAckCookie(); 1288 msg.arg1 = cookie; 1289 Trace.beginAsyncSection(EVENT_POLLING_FRAMES, cookie); 1290 } 1291 try { 1292 mActiveService.send(msg); 1293 } catch (RemoteException e) { 1294 Log.e(TAG, "sendPollingFramesToServiceLocked: Remote service " + mActiveServiceName 1295 + " has died, dropping frames", e); 1296 allowOneTransaction(); 1297 if (Objects.equals(mActiveService, mPaymentService)) { 1298 Log.wtf(TAG, "sendPollingFramesToServiceLocked: Rebinding payment service", e); 1299 bindPaymentServiceLocked(mPaymentServiceUserId, mLastBoundPaymentServiceName); 1300 } 1301 } 1302 } 1303 sendDeactivateToActiveServiceLocked(int reason)1304 void sendDeactivateToActiveServiceLocked(int reason) { 1305 if (mActiveService == null) return; 1306 Message msg = Message.obtain(null, HostApduService.MSG_DEACTIVATED); 1307 msg.arg1 = reason; 1308 try { 1309 mActiveService.send(msg); 1310 } catch (RemoteException e) { 1311 // Don't care 1312 } 1313 } 1314 unbindPaymentServiceLocked()1315 void unbindPaymentServiceLocked() { 1316 Log.d(TAG, "unbindPaymentServiceLocked"); 1317 if (mPaymentServiceBound) { 1318 try { 1319 mContext.unbindService(mPaymentConnection); 1320 if (isMultipleBindingSupported()) { 1321 mComponentNameToConnectionsMap.remove( 1322 new ComponentNameAndUser(mPaymentServiceUserId, mPaymentServiceName)); 1323 } 1324 } catch (Exception e) { 1325 Log.w(TAG, "unbindPaymentServiceLocked: Failed to unbind: " + mPaymentServiceName, 1326 e); 1327 } 1328 mPaymentServiceBound = false; 1329 } 1330 1331 mPaymentService = null; 1332 mPaymentServiceName = null; 1333 mPaymentServiceUserId = -1; 1334 } 1335 bindPaymentServiceLocked(@serIdInt int userId, ComponentName serviceName)1336 void bindPaymentServiceLocked(@UserIdInt int userId, ComponentName serviceName) { 1337 if (nfcHceLatencyEvents()) { 1338 Trace.beginAsyncSection(EVENT_HCE_BIND_PAYMENT_SERVICE, 0); 1339 } 1340 unbindPaymentServiceLocked(); 1341 1342 Log.d(TAG, "bindPaymentServiceLocked:" + serviceName + " for userId:" + userId); 1343 Intent intent = new Intent(HostApduService.SERVICE_INTERFACE); 1344 intent.setComponent(serviceName); 1345 try { 1346 if (isMultipleBindingSupported()) { 1347 mComponentNameToConnectionsMap.put( 1348 new ComponentNameAndUser(userId, serviceName), 1349 new HostEmulationConnection(userId, serviceName, mPaymentConnection)); 1350 } 1351 if (mContext.bindServiceAsUser(intent, mPaymentConnection, 1352 Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, 1353 UserHandle.of(userId))) { 1354 mPaymentServiceBound = true; 1355 mPaymentServiceUserId = userId; 1356 mLastBoundPaymentServiceName = serviceName; 1357 } else { 1358 if (nfcHceLatencyEvents()) { 1359 Trace.endAsyncSection(EVENT_HCE_BIND_PAYMENT_SERVICE, 0); 1360 } 1361 Log.e(TAG, "bindPaymentServiceLocked: Could not bind (persistent) " 1362 + "payment service"); 1363 } 1364 } catch (SecurityException e) { 1365 if (nfcHceLatencyEvents()) { 1366 Trace.endAsyncSection(EVENT_HCE_BIND_PAYMENT_SERVICE, 0); 1367 } 1368 Log.e(TAG, "bindPaymentServiceLocked: Could not bind service " 1369 + "due to security exception"); 1370 } 1371 } 1372 unbindServiceIfNeededLocked()1373 void unbindServiceIfNeededLocked() { 1374 if (isMultipleBindingSupported()) { 1375 if (mServiceName == null 1376 || CompatChanges.isChangeEnabled( 1377 DONT_IMMEDIATELY_UNBIND_SERVICES, 1378 mServiceName.getPackageName(), 1379 UserHandle.of(mServiceUserId))) { 1380 return; 1381 } 1382 if (mServiceName != null) { 1383 mComponentNameToConnectionsMap.remove( 1384 new ComponentNameAndUser(mServiceUserId, mServiceName)); 1385 } 1386 } 1387 1388 if (mServiceBound) { 1389 Log.d(TAG, "unbindServiceIfNeededLocked: service " + mServiceName); 1390 try { 1391 mContext.unbindService(mConnection); 1392 } catch (Exception e) { 1393 Log.w(TAG, "unbindServiceIfNeededLocked: Failed to unbind " + mServiceName, e); 1394 } 1395 mServiceBound = false; 1396 } 1397 1398 mService = null; 1399 mServiceName = null; 1400 mServiceUserId = -1; 1401 } 1402 launchTapAgain(ApduServiceInfo service, String category)1403 void launchTapAgain(ApduServiceInfo service, String category) { 1404 if (mNfcOemExtensionCallback != null) { 1405 try { 1406 mNfcOemExtensionCallback.onLaunchHceTapAgainActivity(service, category); 1407 return; 1408 } catch (RemoteException e) { 1409 Log.e(TAG, "launchTapAgain: onLaunchHceTapAgainActivity failed", e); 1410 } 1411 } 1412 Intent dialogIntent = new Intent(mContext, TapAgainDialog.class); 1413 dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, category); 1414 dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, service); 1415 dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1416 mContext.startActivityAsUser(dialogIntent, 1417 UserHandle.getUserHandleForUid(service.getUid())); 1418 } 1419 launchResolver(String selectedAid, ArrayList<ApduServiceInfo> services, ComponentName failedComponent, String category)1420 void launchResolver(String selectedAid, ArrayList<ApduServiceInfo> services, 1421 ComponentName failedComponent, String category) { 1422 if (mNfcOemExtensionCallback != null) { 1423 try { 1424 mNfcOemExtensionCallback.onLaunchHceAppChooserActivity( 1425 selectedAid, services, failedComponent, category); 1426 return; 1427 } catch (RemoteException e) { 1428 Log.e(TAG, "launchResolver: onLaunchHceAppChooserActivity failed", e); 1429 } 1430 } 1431 Intent intent = new Intent(mContext, AppChooserActivity.class); 1432 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1433 intent.putParcelableArrayListExtra(AppChooserActivity.EXTRA_APDU_SERVICES, services); 1434 intent.putExtra(AppChooserActivity.EXTRA_CATEGORY, category); 1435 if (failedComponent != null) { 1436 intent.putExtra(AppChooserActivity.EXTRA_FAILED_COMPONENT, failedComponent); 1437 } 1438 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 1439 } 1440 findSelectAid(byte[] data)1441 String findSelectAid(byte[] data) { 1442 if (data == null || data.length < SELECT_APDU_HDR_LENGTH + MINIMUM_AID_LENGTH) { 1443 if (DBG) Log.d(TAG, "findSelectAid: Data size too small for SELECT APDU"); 1444 return null; 1445 } 1446 // To accept a SELECT AID for dispatch, we require the following: 1447 // Class byte must be 0x00: logical channel set to zero, no secure messaging, no chaining 1448 // Instruction byte must be 0xA4: SELECT instruction 1449 // P1: must be 0x04: select by application identifier 1450 // P2: File control information is only relevant for higher-level application, 1451 // and we only support "first or only occurrence". 1452 if (data[0] == 0x00 && data[1] == INSTR_SELECT && data[2] == 0x04) { 1453 if (data[3] != 0x00) { 1454 Log.d(TAG, "findSelectAid: Selecting next, last or previous " 1455 + "AID occurrence is not supported"); 1456 } 1457 int aidLength = Byte.toUnsignedInt(data[4]); 1458 if (data.length < SELECT_APDU_HDR_LENGTH + aidLength) { 1459 return null; 1460 } 1461 return bytesToString(data, SELECT_APDU_HDR_LENGTH, aidLength); 1462 } 1463 return null; 1464 } 1465 1466 @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER) 1467 interface NfcAidRoutingListener { onAidConflict(@onNull String aid)1468 void onAidConflict(@NonNull String aid); onAidNotRouted(@onNull String aid)1469 void onAidNotRouted(@NonNull String aid); 1470 } 1471 1472 @Nullable 1473 private NfcAidRoutingListener mAidRoutingListener = null; 1474 1475 @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER) setAidRoutingListener(@ullable NfcAidRoutingListener listener)1476 void setAidRoutingListener(@Nullable NfcAidRoutingListener listener) { 1477 mAidRoutingListener = listener; 1478 } 1479 1480 @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER) notifyAidConflictListener(String aid)1481 private void notifyAidConflictListener(String aid) { 1482 if (mAidRoutingListener != null && aid != null) { 1483 mAidRoutingListener.onAidConflict(aid); 1484 } 1485 } 1486 1487 @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER) notifyAidNotRoutedListener(String aid)1488 private void notifyAidNotRoutedListener(String aid) { 1489 if (mAidRoutingListener != null && aid != null) { 1490 mAidRoutingListener.onAidNotRouted(aid); 1491 } 1492 } 1493 returnToIdleStateLocked()1494 private void returnToIdleStateLocked() { 1495 mPendingPollingLoopFrames = null; 1496 mPollingFramesToSend = null; 1497 mUnprocessedPollingFrames = null; 1498 resetActiveService(); 1499 setPollingLoopStateLocked(PollingLoopState.EVALUATING_POLLING_LOOP); 1500 mState = STATE_IDLE; 1501 } 1502 resetActiveService()1503 private void resetActiveService() { 1504 mActiveService = null; 1505 mActiveServiceName = null; 1506 mActiveServiceUserId = -1; 1507 } 1508 1509 private ServiceConnection mPaymentConnection = new ServiceConnection() { 1510 @Override 1511 public void onServiceConnected(ComponentName name, IBinder service) { 1512 ComponentName paymentServiceName = new ComponentName("", ""); 1513 synchronized (mLock) { 1514 /* Preferred Payment Service has been changed. */ 1515 if (!mLastBoundPaymentServiceName.equals(name)) { 1516 Log.i(TAG, "onServiceConnected: Ignoring bound payment service, " + name 1517 + " != " + mLastBoundPaymentServiceName); 1518 return; 1519 } 1520 mPaymentServiceName = name; 1521 mPaymentService = new Messenger(service); 1522 paymentServiceName = mPaymentServiceName; 1523 if (isMultipleBindingSupported()) { 1524 if (mComponentNameToConnectionsMap.containsKey( 1525 new ComponentNameAndUser(mPaymentServiceUserId, name))) { 1526 mComponentNameToConnectionsMap.get( 1527 new ComponentNameAndUser(mPaymentServiceUserId, name)).mMessenger = 1528 mPaymentService; 1529 } else { 1530 mComponentNameToConnectionsMap.put( 1531 new ComponentNameAndUser(mPaymentServiceUserId, name), 1532 new HostEmulationConnection(mPaymentServiceUserId, name, 1533 this, mPaymentService)); 1534 } 1535 } 1536 Log.i(TAG, "onServiceConnected: Payment service bound: " + name); 1537 if (nfcHceLatencyEvents()) { 1538 Trace.endAsyncSection(EVENT_HCE_BIND_PAYMENT_SERVICE, 0); 1539 } 1540 } 1541 NfcInjector.getInstance().getNfcEventLog().logEvent( 1542 NfcEventProto.EventType.newBuilder() 1543 .setPaymentServiceBindState( 1544 NfcEventProto.NfcPaymentServiceBindState.newBuilder() 1545 .setBindState(NfcEventProto.BindState.SERVICE_CONNECTED) 1546 .setComponentInfo( 1547 NfcEventProto.NfcComponentInfo.newBuilder() 1548 .setPackageName( 1549 paymentServiceName.getPackageName()) 1550 .setClassName( 1551 paymentServiceName.getClassName()) 1552 .build()) 1553 .build()) 1554 .build()); 1555 1556 if (mPollingFramesToSend != null && mPollingFramesToSend.containsKey(name)) { 1557 sendPollingFramesToServiceLocked(mPaymentService, mPollingFramesToSend.get(name)); 1558 mPollingFramesToSend.remove(name); 1559 if (mUnprocessedPollingFrames != null) { 1560 ArrayList unprocessedPollingFrames = mUnprocessedPollingFrames; 1561 mUnprocessedPollingFrames = null; 1562 onPollingLoopDetected(unprocessedPollingFrames); 1563 } 1564 } 1565 } 1566 1567 @Override 1568 public void onServiceDisconnected(ComponentName name) { 1569 Log.i(TAG, "onServiceDisconnected: " + name); 1570 ComponentName paymentServiceName = new ComponentName("", ""); 1571 synchronized (mLock) { 1572 if (isMultipleBindingSupported()) { 1573 ComponentNameAndUser nameAndUser = 1574 new ComponentNameAndUser(mPaymentServiceUserId, name); 1575 mComponentNameToConnectionsMap.remove(nameAndUser); 1576 } 1577 paymentServiceName = mPaymentServiceName; 1578 mPaymentService = null; 1579 mPaymentServiceName = null; 1580 } 1581 NfcInjector.getInstance().getNfcEventLog().logEvent( 1582 NfcEventProto.EventType.newBuilder() 1583 .setPaymentServiceBindState( 1584 NfcEventProto.NfcPaymentServiceBindState.newBuilder() 1585 .setBindState(NfcEventProto.BindState.SERVICE_DISCONNECTED) 1586 .setComponentInfo( 1587 NfcEventProto.NfcComponentInfo.newBuilder() 1588 .setPackageName( 1589 paymentServiceName.getPackageName()) 1590 .setClassName( 1591 paymentServiceName.getClassName()) 1592 .build()) 1593 .build()) 1594 .build()); 1595 } 1596 1597 @Override 1598 public void onBindingDied(ComponentName name) { 1599 Log.i(TAG, "onBindingDied: " + name); 1600 ComponentName paymentServiceName = new ComponentName("", ""); 1601 synchronized (mLock) { 1602 if (mPaymentServiceName != null) paymentServiceName = mPaymentServiceName; 1603 if (mPaymentServiceUserId >= 0) { 1604 bindPaymentServiceLocked(mPaymentServiceUserId, mLastBoundPaymentServiceName); 1605 } 1606 } 1607 NfcInjector.getInstance().getNfcEventLog().logEvent( 1608 NfcEventProto.EventType.newBuilder() 1609 .setPaymentServiceBindState( 1610 NfcEventProto.NfcPaymentServiceBindState.newBuilder() 1611 .setBindState(NfcEventProto.BindState.SERVICE_BINDING_DIED) 1612 .setComponentInfo( 1613 NfcEventProto.NfcComponentInfo.newBuilder() 1614 .setPackageName( 1615 paymentServiceName.getPackageName()) 1616 .setClassName( 1617 paymentServiceName.getClassName()) 1618 .build()) 1619 .build()) 1620 .build()); 1621 } 1622 }; 1623 1624 class HostEmulationServiceConnection implements ServiceConnection { 1625 @UserIdInt int mUserId; 1626 HostEmulationServiceConnection(@serIdInt int userId)1627 HostEmulationServiceConnection(@UserIdInt int userId) { 1628 mUserId = userId; 1629 } 1630 1631 @Override onServiceConnected(ComponentName name, IBinder service)1632 public void onServiceConnected(ComponentName name, IBinder service) { 1633 synchronized (mLock) { 1634 ComponentNameAndUser preferredUserAndService = mAidCache.getPreferredService(); 1635 ComponentName preferredServiceName = 1636 preferredUserAndService == null ? null : 1637 preferredUserAndService.getComponentName(); 1638 /* Service is already deactivated and not preferred, don't bind */ 1639 if (mState == STATE_IDLE && !name.equals(preferredServiceName)) { 1640 return; 1641 } 1642 Messenger messenger = new Messenger(service); 1643 if (isMultipleBindingSupported()) { 1644 ComponentNameAndUser key = new ComponentNameAndUser(mUserId, name); 1645 if (mComponentNameToConnectionsMap.containsKey(key)) { 1646 mComponentNameToConnectionsMap.get(key).mMessenger = messenger; 1647 } else { 1648 mComponentNameToConnectionsMap.put(key, 1649 new HostEmulationConnection(mUserId, name, this, messenger)); 1650 } 1651 } else { 1652 mService = messenger; 1653 mServiceName = name; 1654 mServiceBound = true; 1655 } 1656 1657 if (nfcHceLatencyEvents()) { 1658 Trace.endAsyncSection(EVENT_HCE_BIND_SERVICE, 0); 1659 } 1660 Log.d(TAG, "onServiceConnected: Service bound: " + name); 1661 1662 // Send pending select APDU 1663 if (mSelectApdu != null) { 1664 if (mStatsdUtils != null) { 1665 mStatsdUtils.notifyCardEmulationEventServiceBound(); 1666 } 1667 NfcInjector.getInstance().getNfcEventLog().logEvent( 1668 NfcEventProto.EventType.newBuilder() 1669 .setCeRoutedAid( 1670 NfcEventProto.NfcCeRoutedAid.newBuilder() 1671 .setAid(mLastSelectedAid == null 1672 ? "" : mLastSelectedAid) 1673 .setComponentInfo( 1674 NfcEventProto.NfcComponentInfo.newBuilder() 1675 .setPackageName( 1676 name.getPackageName()) 1677 .setClassName( 1678 name.getClassName()) 1679 .build()) 1680 .build()) 1681 .build()); 1682 sendDataToServiceLocked(messenger, mSelectApdu); 1683 mSelectApdu = null; 1684 } else if (mPollingFramesToSend != null && mPollingFramesToSend.containsKey(name)) { 1685 sendPollingFramesToServiceLocked(messenger, mPollingFramesToSend.get(name)); 1686 mPollingFramesToSend.remove(name); 1687 if (mUnprocessedPollingFrames != null) { 1688 ArrayList unprocessedPollingFrames = mUnprocessedPollingFrames; 1689 mUnprocessedPollingFrames = null; 1690 onPollingLoopDetected(unprocessedPollingFrames); 1691 } 1692 } else { 1693 Log.d(TAG, "onServiceConnected: bound with nothing to send"); 1694 } 1695 } 1696 } 1697 1698 @Override onServiceDisconnected(ComponentName name)1699 public void onServiceDisconnected(ComponentName name) { 1700 synchronized (mLock) { 1701 Log.d(TAG, "onServiceDisconnected: unbound: " + name); 1702 if (isMultipleBindingSupported()) { 1703 ComponentNameAndUser nameAndUser = new ComponentNameAndUser(mUserId, name); 1704 mComponentNameToConnectionsMap.remove(nameAndUser); 1705 } else { 1706 mService = null; 1707 mServiceName = null; 1708 mServiceBound = false; 1709 } 1710 } 1711 } 1712 }; 1713 1714 private ServiceConnection mConnection = 1715 new HostEmulationServiceConnection(UserHandle.CURRENT.getIdentifier()); 1716 1717 class MessageHandler extends Handler { 1718 @Override handleMessage(Message msg)1719 public void handleMessage(Message msg) { 1720 synchronized(mLock) { 1721 if (mActiveService == null) { 1722 Log.d(TAG, "handleMessage: Dropping service response message; " 1723 + "service no longer active."); 1724 return; 1725 } else if (!msg.replyTo.getBinder().equals(mActiveService.getBinder())) { 1726 Log.d(TAG, "handleMessage: Dropping service response message; " 1727 + "service no longer bound."); 1728 return; 1729 } 1730 } 1731 if (msg.what == HostApduService.MSG_RESPONSE_APDU) { 1732 Bundle dataBundle = msg.getData(); 1733 if (dataBundle == null) { 1734 return; 1735 } 1736 byte[] data = dataBundle.getByteArray(DATA_KEY); 1737 if (data == null || data.length == 0) { 1738 Log.e(TAG, "handleMessage: Dropping empty R-APDU"); 1739 return; 1740 } 1741 int state; 1742 synchronized(mLock) { 1743 state = mState; 1744 } 1745 if (state == STATE_XFER) { 1746 Log.d(TAG, "handleMessage: Sending data"); 1747 NfcService.getInstance().sendData(data); 1748 if (mStatsdUtils != null) { 1749 mStatsdUtils.notifyCardEmulationEventResponseReceived(); 1750 } 1751 } else { 1752 Log.d(TAG, 1753 "handleMessage: Dropping data, wrong state " + Integer.toString(state)); 1754 } 1755 1756 if (nfcHceLatencyEvents()) { 1757 try { 1758 Message ackMsg = Message.obtain(null, 1759 HostApduService.MSG_RESPONSE_APDU_ACK); 1760 ackMsg.arg1 = msg.arg1; 1761 ackMsg.replyTo = mMessenger; 1762 msg.replyTo.send(ackMsg); 1763 } catch (RemoteException e) { 1764 Log.e(TAG, "handleMessage: Failed to acknowledge MSG_RESPONSE_APDU", e); 1765 } 1766 } 1767 } else if (msg.what == HostApduService.MSG_UNHANDLED) { 1768 synchronized (mLock) { 1769 Log.d(TAG, "handleMessage: Received MSG_UNHANDLED"); 1770 AidResolveInfo resolveInfo = mAidCache.resolveAid(mLastSelectedAid); 1771 1772 if (resolveInfo.services.size() > 0) { 1773 NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, mLastSelectedAid); 1774 if (android.nfc.Flags.nfcEventListener()) { 1775 notifyAidConflictListener(mLastSelectedAid); 1776 } 1777 launchResolver(mLastSelectedAid, 1778 (ArrayList<ApduServiceInfo>)resolveInfo.services, 1779 mActiveServiceName, resolveInfo.category); 1780 } 1781 } 1782 } else if (msg.what == HostApduService.MSG_COMMAND_APDU_ACK) { 1783 if (nfcHceLatencyEvents()) { 1784 Trace.endAsyncSection(EVENT_HCE_COMMAND_APDU, msg.arg1); 1785 } 1786 } else if (msg.what == HostApduService.MSG_POLLING_LOOP_ACK) { 1787 if (nfcHceLatencyEvents()) { 1788 Trace.endAsyncSection(EVENT_POLLING_FRAMES, msg.arg1); 1789 } 1790 } 1791 } 1792 } 1793 bytesToString(byte[] bytes, int offset, int length)1794 static String bytesToString(byte[] bytes, int offset, int length) { 1795 final char[] hexChars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 1796 char[] chars = new char[length * 2]; 1797 int byteValue; 1798 for (int j = 0; j < length; j++) { 1799 byteValue = bytes[offset + j] & 0xFF; 1800 chars[j * 2] = hexChars[byteValue >>> 4]; 1801 chars[j * 2 + 1] = hexChars[byteValue & 0x0F]; 1802 } 1803 return new String(chars); 1804 } 1805 dump(FileDescriptor fd, PrintWriter pw, String[] args)1806 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1807 pw.println("Bound HCE-A/HCE-B services: "); 1808 if (mPaymentServiceBound) { 1809 pw.println(" payment: " + mPaymentServiceName); 1810 } 1811 if (isMultipleBindingSupported() && !mComponentNameToConnectionsMap.isEmpty()) { 1812 pw.println(" others: "); 1813 for (Map.Entry<ComponentNameAndUser, HostEmulationConnection> entry : 1814 mComponentNameToConnectionsMap.entrySet()) { 1815 pw.println(" " + entry.getKey()); 1816 } 1817 } else if (mServiceBound) { 1818 pw.println(" other: " + mServiceName); 1819 } 1820 } 1821 1822 /** 1823 * Dump debugging information as a HostEmulationManagerProto 1824 * 1825 * Note: 1826 * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto 1827 * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and 1828 * {@link ProtoOutputStream#end(long)} after. 1829 * Never reuse a proto field number. When removing a field, mark it as reserved. 1830 */ dumpDebug(ProtoOutputStream proto)1831 void dumpDebug(ProtoOutputStream proto) { 1832 if (mPaymentServiceBound) { 1833 Utils.dumpDebugComponentName( 1834 mPaymentServiceName, proto, HostEmulationManagerProto.PAYMENT_SERVICE_NAME); 1835 } 1836 // TODO make this a repeated field and return all the services 1837 if (mServiceBound) { 1838 Utils.dumpDebugComponentName( 1839 mServiceName, proto, HostEmulationManagerProto.SERVICE_NAME); 1840 } 1841 } 1842 isMultipleBindingSupported()1843 boolean isMultipleBindingSupported() { 1844 return Flags.allowMultipleHceBindings(); 1845 } 1846 1847 @VisibleForTesting getState()1848 public int getState() { 1849 return mState; 1850 } 1851 1852 @VisibleForTesting getServiceConnection()1853 public ServiceConnection getServiceConnection() { 1854 return mConnection; 1855 } 1856 1857 @VisibleForTesting getPaymentConnection()1858 public ServiceConnection getPaymentConnection() { 1859 return mPaymentConnection; 1860 } 1861 1862 @VisibleForTesting getMessenger()1863 public IBinder getMessenger() { 1864 if (mActiveService != null) { 1865 return mActiveService.getBinder(); 1866 } 1867 return null; 1868 } 1869 1870 @VisibleForTesting getLocalMessenger()1871 public Messenger getLocalMessenger() { 1872 return mMessenger; 1873 } 1874 1875 @VisibleForTesting getServiceName()1876 public ComponentName getServiceName() { 1877 return mLastBoundPaymentServiceName; 1878 } 1879 1880 @VisibleForTesting isServiceBounded(@serIdInt int userId, ComponentName componentName)1881 public Boolean isServiceBounded(@UserIdInt int userId, ComponentName componentName) { 1882 if (isMultipleBindingSupported()) { 1883 return mComponentNameToConnectionsMap.containsKey( 1884 new ComponentNameAndUser(userId, componentName)); 1885 } else { 1886 return mServiceBound; 1887 } 1888 } 1889 1890 @VisibleForTesting getPollingLoopFilters()1891 public Map<Integer, Map<String, List<ApduServiceInfo>>> getPollingLoopFilters() { 1892 return mPollingLoopFilters; 1893 } 1894 1895 @VisibleForTesting getPollingLoopPatternFilters()1896 public Map<Integer, Map<Pattern, List<ApduServiceInfo>>> getPollingLoopPatternFilters() { 1897 return mPollingLoopPatternFilters; 1898 } 1899 } 1900