1 /* 2 * Copyright (C) 2024 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 org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.anyInt; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.verifyNoMoreInteractions; 24 import static org.mockito.Mockito.when; 25 26 import android.app.ActivityManager; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.nfc.cardemulation.ApduServiceInfo; 30 import android.nfc.cardemulation.CardEmulation; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.util.Pair; 34 35 import androidx.test.ext.junit.runners.AndroidJUnit4; 36 37 import com.android.dx.mockito.inline.extended.ExtendedMockito; 38 import com.android.nfc.NfcService; 39 40 import org.junit.After; 41 import org.junit.Assert; 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Captor; 47 import org.mockito.Mock; 48 import org.mockito.Mockito; 49 import org.mockito.MockitoAnnotations; 50 import org.mockito.MockitoSession; 51 import org.mockito.quality.Strictness; 52 53 import java.util.ArrayList; 54 import java.util.HashMap; 55 import java.util.List; 56 57 @RunWith(AndroidJUnit4.class) 58 public class RegisteredAidCacheTest { 59 60 private static final String PREFIX_AID = "ASDASD*"; 61 private static final String SUBSET_AID = "ASDASD#"; 62 private static final String EXACT_AID = "TASDASD"; 63 private static final String PAYMENT_AID_1 = "A000000004101012"; 64 private static final String PAYMENT_AID_2 = "A000000004101018"; 65 private static final String NON_PAYMENT_AID_1 = "F053414950454D"; 66 private static final String PREFIX_PAYMENT_AID = "A000000004*"; 67 private static final String NFC_FOREGROUND_PACKAGE_NAME = "com.android.test.foregroundnfc"; 68 private static final String NON_PAYMENT_NFC_PACKAGE_NAME = "com.android.test.nonpaymentnfc"; 69 private static final String WALLET_HOLDER_PACKAGE_NAME = "com.android.test.walletroleholder"; 70 private static final String WALLET_HOLDER_2_PACKAGE_NAME = "com.android.test.walletroleholder2"; 71 72 private static final ComponentName WALLET_PAYMENT_SERVICE 73 = new ComponentName(WALLET_HOLDER_PACKAGE_NAME, 74 "com.android.test.walletroleholder.WalletRoleHolderApduService"); 75 76 private static final ComponentName WALLET_PAYMENT_SERVICE_2 77 = new ComponentName(WALLET_HOLDER_PACKAGE_NAME, 78 "com.android.test.walletroleholder.XWalletRoleHolderApduService"); 79 private static final ComponentName FOREGROUND_SERVICE 80 = new ComponentName(NFC_FOREGROUND_PACKAGE_NAME, 81 "com.android.test.foregroundnfc.ForegroundApduService"); 82 private static final ComponentName NON_PAYMENT_SERVICE = 83 new ComponentName(NON_PAYMENT_NFC_PACKAGE_NAME, 84 "com.android.test.nonpaymentnfc.NonPaymentApduService"); 85 86 private static final ComponentName PAYMENT_SERVICE = 87 new ComponentName(WALLET_HOLDER_2_PACKAGE_NAME, 88 "com.android.test.walletroleholder.WalletRoleHolderXApduService"); 89 90 private static final int USER_ID = 0; 91 private static final UserHandle USER_HANDLE = UserHandle.of(USER_ID); 92 93 @Mock 94 private Context mContext; 95 @Mock 96 private WalletRoleObserver mWalletRoleObserver; 97 @Mock 98 private AidRoutingManager mAidRoutingManager; 99 @Mock 100 private UserManager mUserManager; 101 @Mock 102 private NfcService mNfcService; 103 @Captor 104 private ArgumentCaptor<HashMap<String, AidRoutingManager.AidEntry>> mRoutingEntryMapCaptor; 105 106 private MockitoSession mStaticMockSession; 107 108 RegisteredAidCache mRegisteredAidCache; 109 110 @Before setUp()111 public void setUp() { 112 mStaticMockSession = ExtendedMockito.mockitoSession() 113 .mockStatic(ActivityManager.class) 114 .mockStatic(NfcService.class) 115 .strictness(Strictness.LENIENT) 116 .initMocks(this) 117 .startMocking(); 118 when(ActivityManager.getCurrentUser()).thenReturn(USER_ID); 119 when(NfcService.getInstance()).thenReturn(mNfcService); 120 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_1_0); 121 when(mUserManager.getProfileParent(eq(USER_HANDLE))).thenReturn(USER_HANDLE); 122 when(mContext.createContextAsUser( 123 any(), anyInt())).thenReturn(mContext); 124 when(mContext.getSystemService(eq(UserManager.class))).thenReturn(mUserManager); 125 } 126 127 @After tearDown()128 public void tearDown() { 129 mStaticMockSession.finishMocking(); 130 } 131 132 @Test testConstructor_supportsPrefixAndSubset()133 public void testConstructor_supportsPrefixAndSubset() { 134 supportPrefixAndSubset(true); 135 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 136 mAidRoutingManager); 137 138 verify(mAidRoutingManager).supportsAidPrefixRouting(); 139 verify(mAidRoutingManager).supportsAidSubsetRouting(); 140 Assert.assertTrue(mRegisteredAidCache.supportsAidPrefixRegistration()); 141 Assert.assertTrue(mRegisteredAidCache.supportsAidSubsetRegistration()); 142 } 143 144 @Test testConstructor_doesNotSupportsPrefixAndSubset()145 public void testConstructor_doesNotSupportsPrefixAndSubset() { 146 supportPrefixAndSubset(false); 147 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 148 mAidRoutingManager); 149 150 verify(mAidRoutingManager).supportsAidPrefixRouting(); 151 verify(mAidRoutingManager).supportsAidSubsetRouting(); 152 Assert.assertFalse(mRegisteredAidCache.supportsAidPrefixRegistration()); 153 Assert.assertFalse(mRegisteredAidCache.supportsAidSubsetRegistration()); 154 } 155 156 @Test testAidStaticMethods()157 public void testAidStaticMethods() { 158 Assert.assertTrue(RegisteredAidCache.isPrefix(PREFIX_AID)); 159 Assert.assertTrue(RegisteredAidCache.isSubset(SUBSET_AID)); 160 Assert.assertTrue(RegisteredAidCache.isExact(EXACT_AID)); 161 162 Assert.assertFalse(RegisteredAidCache.isPrefix(EXACT_AID)); 163 Assert.assertFalse(RegisteredAidCache.isSubset(EXACT_AID)); 164 Assert.assertFalse(RegisteredAidCache.isExact(PREFIX_AID)); 165 Assert.assertFalse(RegisteredAidCache.isExact(SUBSET_AID)); 166 } 167 168 @Test testAidConflictResolution_walletRoleEnabledNfcDisabled_foregroundWins()169 public void testAidConflictResolution_walletRoleEnabledNfcDisabled_foregroundWins() { 170 setWalletRoleFlag(true); 171 supportPrefixAndSubset(false); 172 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 173 mAidRoutingManager); 174 mRegisteredAidCache.mNfcEnabled = false; 175 176 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 177 apduServiceInfos.add(createServiceInfoForAidRouting( 178 WALLET_PAYMENT_SERVICE, 179 true, 180 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 181 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 182 false, 183 false, 184 USER_ID, 185 true)); 186 apduServiceInfos.add(createServiceInfoForAidRouting( 187 FOREGROUND_SERVICE, 188 true, 189 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 190 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 191 false, 192 false, 193 USER_ID, 194 true)); 195 apduServiceInfos.add(createServiceInfoForAidRouting( 196 NON_PAYMENT_SERVICE, 197 true, 198 List.of(NON_PAYMENT_AID_1), 199 List.of(CardEmulation.CATEGORY_OTHER), 200 false, 201 false, 202 USER_ID, 203 true)); 204 205 mRegisteredAidCache.generateUserApduServiceInfoLocked(USER_ID, apduServiceInfos); 206 mRegisteredAidCache.generateServiceMapLocked(apduServiceInfos); 207 mRegisteredAidCache.onPreferredForegroundServiceChanged(USER_ID, FOREGROUND_SERVICE); 208 RegisteredAidCache.AidResolveInfo resolveInfo 209 = mRegisteredAidCache.resolveAid(PAYMENT_AID_1); 210 211 verify(mAidRoutingManager).supportsAidPrefixRouting(); 212 verify(mAidRoutingManager).supportsAidSubsetRouting(); 213 Assert.assertEquals(resolveInfo.defaultService.getComponent(), FOREGROUND_SERVICE); 214 Assert.assertEquals(mRegisteredAidCache.getPreferredService(), 215 new Pair<>(USER_ID, FOREGROUND_SERVICE)); 216 Assert.assertEquals(resolveInfo.services.size(), 1); 217 Assert.assertEquals(resolveInfo.category, CardEmulation.CATEGORY_PAYMENT); 218 verifyNoMoreInteractions(mAidRoutingManager); 219 } 220 221 @Test testAidConflictResolution_walletRoleEnabledNfcEnabled_walletWins()222 public void testAidConflictResolution_walletRoleEnabledNfcEnabled_walletWins() { 223 setWalletRoleFlag(true); 224 supportPrefixAndSubset(false); 225 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 226 mAidRoutingManager); 227 mRegisteredAidCache.mNfcEnabled = true; 228 229 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 230 apduServiceInfos.add(createServiceInfoForAidRouting( 231 WALLET_PAYMENT_SERVICE, 232 true, 233 List.of(PAYMENT_AID_1), 234 List.of(CardEmulation.CATEGORY_PAYMENT), 235 false, 236 true, 237 USER_ID, 238 true)); 239 apduServiceInfos.add(createServiceInfoForAidRouting( 240 PAYMENT_SERVICE, 241 true, 242 List.of(PAYMENT_AID_1), 243 List.of(CardEmulation.CATEGORY_PAYMENT), 244 false, 245 true, 246 USER_ID, 247 true)); 248 apduServiceInfos.add(createServiceInfoForAidRouting( 249 NON_PAYMENT_SERVICE, 250 true, 251 List.of(NON_PAYMENT_AID_1), 252 List.of(CardEmulation.CATEGORY_OTHER), 253 false, 254 false, 255 USER_ID, 256 true)); 257 258 mRegisteredAidCache.generateUserApduServiceInfoLocked(USER_ID, apduServiceInfos); 259 mRegisteredAidCache.generateServiceMapLocked(apduServiceInfos); 260 mRegisteredAidCache.onWalletRoleHolderChanged(WALLET_HOLDER_PACKAGE_NAME, USER_ID); 261 RegisteredAidCache.AidResolveInfo paymentResolveInfo 262 = mRegisteredAidCache.resolveAid(PAYMENT_AID_1); 263 RegisteredAidCache.AidResolveInfo nonPaymentResolveInfo 264 = mRegisteredAidCache.resolveAid(NON_PAYMENT_AID_1); 265 266 Assert.assertEquals(paymentResolveInfo.defaultService.getComponent(), 267 WALLET_PAYMENT_SERVICE); 268 Assert.assertEquals(paymentResolveInfo.services.size(), 1); 269 Assert.assertEquals(paymentResolveInfo.category, CardEmulation.CATEGORY_PAYMENT); 270 Assert.assertEquals(nonPaymentResolveInfo.defaultService.getComponent(), 271 NON_PAYMENT_SERVICE); 272 Assert.assertEquals(nonPaymentResolveInfo.services.size(), 1); 273 Assert.assertEquals(nonPaymentResolveInfo.category, CardEmulation.CATEGORY_OTHER); 274 verify(mAidRoutingManager).configureRouting(mRoutingEntryMapCaptor.capture(), 275 eq(false)); 276 HashMap<String, AidRoutingManager.AidEntry> routingEntries = 277 mRoutingEntryMapCaptor.getValue(); 278 Assert.assertTrue(routingEntries.containsKey(PAYMENT_AID_1)); 279 Assert.assertTrue(routingEntries.containsKey(NON_PAYMENT_AID_1)); 280 Assert.assertTrue(routingEntries.get(PAYMENT_AID_1).isOnHost); 281 Assert.assertTrue(routingEntries.get(NON_PAYMENT_AID_1).isOnHost); 282 Assert.assertNull(routingEntries.get(PAYMENT_AID_1).offHostSE); 283 Assert.assertNull(routingEntries.get(NON_PAYMENT_AID_1).offHostSE); 284 Assert.assertTrue(mRegisteredAidCache.isRequiresScreenOnServiceExist()); 285 } 286 287 @Test testAidConflictResolution_walletRoleEnabledNfcEnabledPreFixAid_walletWins()288 public void testAidConflictResolution_walletRoleEnabledNfcEnabledPreFixAid_walletWins() { 289 setWalletRoleFlag(true); 290 supportPrefixAndSubset(true); 291 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 292 mAidRoutingManager); 293 mRegisteredAidCache.mNfcEnabled = true; 294 295 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 296 apduServiceInfos.add(createServiceInfoForAidRouting( 297 WALLET_PAYMENT_SERVICE, 298 true, 299 List.of(PREFIX_PAYMENT_AID), 300 List.of(CardEmulation.CATEGORY_PAYMENT), 301 false, 302 true, 303 USER_ID, 304 true)); 305 apduServiceInfos.add(createServiceInfoForAidRouting( 306 PAYMENT_SERVICE, 307 true, 308 List.of(PAYMENT_AID_1), 309 List.of(CardEmulation.CATEGORY_PAYMENT), 310 false, 311 true, 312 USER_ID, 313 true)); 314 apduServiceInfos.add(createServiceInfoForAidRouting( 315 NON_PAYMENT_SERVICE, 316 true, 317 List.of(NON_PAYMENT_AID_1), 318 List.of(CardEmulation.CATEGORY_OTHER), 319 false, 320 false, 321 USER_ID, 322 true)); 323 324 mRegisteredAidCache.generateUserApduServiceInfoLocked(USER_ID, apduServiceInfos); 325 mRegisteredAidCache.generateServiceMapLocked(apduServiceInfos); 326 mRegisteredAidCache.onWalletRoleHolderChanged(WALLET_HOLDER_PACKAGE_NAME, USER_ID); 327 RegisteredAidCache.AidResolveInfo paymentResolveInfo 328 = mRegisteredAidCache.resolveAid(PAYMENT_AID_1); 329 RegisteredAidCache.AidResolveInfo nonPaymentResolveInfo 330 = mRegisteredAidCache.resolveAid(NON_PAYMENT_AID_1); 331 332 Assert.assertEquals(paymentResolveInfo.defaultService.getComponent(), 333 WALLET_PAYMENT_SERVICE); 334 Assert.assertEquals(paymentResolveInfo.services.size(), 1); 335 Assert.assertEquals(paymentResolveInfo.category, CardEmulation.CATEGORY_PAYMENT); 336 Assert.assertEquals(nonPaymentResolveInfo.defaultService.getComponent(), 337 NON_PAYMENT_SERVICE); 338 Assert.assertEquals(nonPaymentResolveInfo.services.size(), 1); 339 Assert.assertEquals(nonPaymentResolveInfo.category, CardEmulation.CATEGORY_OTHER); 340 } 341 342 @Test testAidConflictResolution_walletRoleEnabled_twoServicesOnWallet_firstServiceWins()343 public void testAidConflictResolution_walletRoleEnabled_twoServicesOnWallet_firstServiceWins() { 344 setWalletRoleFlag(true); 345 supportPrefixAndSubset(false); 346 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 347 mAidRoutingManager); 348 349 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 350 apduServiceInfos.add(createServiceInfoForAidRouting( 351 WALLET_PAYMENT_SERVICE, 352 true, 353 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 354 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 355 false, 356 false, 357 USER_ID, 358 true)); 359 apduServiceInfos.add(createServiceInfoForAidRouting( 360 WALLET_PAYMENT_SERVICE_2, 361 true, 362 List.of(PAYMENT_AID_1), 363 List.of(CardEmulation.CATEGORY_PAYMENT), 364 false, 365 false, 366 USER_ID, 367 true)); 368 apduServiceInfos.add(createServiceInfoForAidRouting( 369 PAYMENT_SERVICE, 370 true, 371 List.of(PAYMENT_AID_1), 372 List.of(CardEmulation.CATEGORY_PAYMENT), 373 false, 374 false, 375 USER_ID, 376 true)); 377 378 mRegisteredAidCache.generateUserApduServiceInfoLocked(USER_ID, apduServiceInfos); 379 mRegisteredAidCache.generateServiceMapLocked(apduServiceInfos); 380 mRegisteredAidCache.onWalletRoleHolderChanged(WALLET_HOLDER_PACKAGE_NAME, USER_ID); 381 RegisteredAidCache.AidResolveInfo resolveInfo 382 = mRegisteredAidCache.resolveAid(PAYMENT_AID_1); 383 Assert.assertEquals(resolveInfo.defaultService.getComponent(), WALLET_PAYMENT_SERVICE); 384 Assert.assertEquals(resolveInfo.services.size(), 2); 385 Assert.assertEquals(resolveInfo.category, CardEmulation.CATEGORY_PAYMENT); 386 } 387 388 @Test testOnServicesUpdated_walletRoleEnabled()389 public void testOnServicesUpdated_walletRoleEnabled() { 390 setWalletRoleFlag(true); 391 supportPrefixAndSubset(false); 392 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 393 mAidRoutingManager); 394 mRegisteredAidCache.mNfcEnabled = true; 395 396 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 397 apduServiceInfos.add(createServiceInfoForAidRouting( 398 WALLET_PAYMENT_SERVICE, 399 true, 400 List.of(PAYMENT_AID_1), 401 List.of(CardEmulation.CATEGORY_PAYMENT), 402 false, 403 true, 404 USER_ID, 405 true)); 406 apduServiceInfos.add(createServiceInfoForAidRouting( 407 PAYMENT_SERVICE, 408 true, 409 List.of(PAYMENT_AID_1), 410 List.of(CardEmulation.CATEGORY_PAYMENT), 411 false, 412 true, 413 USER_ID, 414 true)); 415 apduServiceInfos.add(createServiceInfoForAidRouting( 416 NON_PAYMENT_SERVICE, 417 true, 418 List.of(NON_PAYMENT_AID_1), 419 List.of(CardEmulation.CATEGORY_OTHER), 420 false, 421 true, 422 USER_ID, 423 true)); 424 425 mRegisteredAidCache.onServicesUpdated(USER_ID, apduServiceInfos); 426 427 verify(mAidRoutingManager).supportsAidPrefixRouting(); 428 verify(mAidRoutingManager).supportsAidSubsetRouting(); 429 Assert.assertTrue(mRegisteredAidCache.mAidServices.containsKey(PAYMENT_AID_1)); 430 Assert.assertTrue(mRegisteredAidCache.mAidServices.containsKey(NON_PAYMENT_AID_1)); 431 Assert.assertEquals(mRegisteredAidCache.mAidServices.get(PAYMENT_AID_1).size(), 2); 432 Assert.assertEquals(mRegisteredAidCache.mAidServices.get(NON_PAYMENT_AID_1).size(), 1); 433 Assert.assertEquals(mRegisteredAidCache.mAidServices.get(PAYMENT_AID_1).get(0) 434 .service.getComponent(), WALLET_PAYMENT_SERVICE); 435 Assert.assertEquals(mRegisteredAidCache.mAidServices.get(PAYMENT_AID_1).get(1) 436 .service.getComponent(), PAYMENT_SERVICE); 437 verify(mAidRoutingManager).configureRouting(mRoutingEntryMapCaptor.capture(), 438 eq(false)); 439 HashMap<String, AidRoutingManager.AidEntry> routingEntries = 440 mRoutingEntryMapCaptor.getValue(); 441 Assert.assertTrue(routingEntries.containsKey(NON_PAYMENT_AID_1)); 442 Assert.assertTrue(routingEntries.get(NON_PAYMENT_AID_1).isOnHost); 443 Assert.assertNull(routingEntries.get(NON_PAYMENT_AID_1).offHostSE); 444 Assert.assertTrue(mRegisteredAidCache.isRequiresScreenOnServiceExist()); 445 } 446 447 @Test testOnNfcEnabled()448 public void testOnNfcEnabled() { 449 setWalletRoleFlag(true); 450 supportPrefixAndSubset(false); 451 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 452 mAidRoutingManager); 453 454 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 455 apduServiceInfos.add(createServiceInfoForAidRouting( 456 WALLET_PAYMENT_SERVICE, 457 true, 458 List.of(PAYMENT_AID_1), 459 List.of(CardEmulation.CATEGORY_PAYMENT), 460 false, 461 false, 462 USER_ID, 463 true)); 464 apduServiceInfos.add(createServiceInfoForAidRouting( 465 PAYMENT_SERVICE, 466 true, 467 List.of(PAYMENT_AID_1), 468 List.of(CardEmulation.CATEGORY_PAYMENT), 469 false, 470 false, 471 USER_ID, 472 true)); 473 apduServiceInfos.add(createServiceInfoForAidRouting( 474 NON_PAYMENT_SERVICE, 475 true, 476 List.of(NON_PAYMENT_AID_1), 477 List.of(CardEmulation.CATEGORY_OTHER), 478 false, 479 false, 480 USER_ID, 481 true)); 482 483 mRegisteredAidCache.generateUserApduServiceInfoLocked(USER_ID, apduServiceInfos); 484 mRegisteredAidCache.generateServiceMapLocked(apduServiceInfos); 485 mRegisteredAidCache.onNfcEnabled(); 486 487 verify(mAidRoutingManager).supportsAidPrefixRouting(); 488 verify(mAidRoutingManager).supportsAidSubsetRouting(); 489 verify(mAidRoutingManager).configureRouting(mRoutingEntryMapCaptor.capture(), 490 eq(false)); 491 Assert.assertFalse(mRegisteredAidCache.isRequiresScreenOnServiceExist()); 492 } 493 494 @Test testOnNfcDisabled()495 public void testOnNfcDisabled() { 496 setWalletRoleFlag(true); 497 supportPrefixAndSubset(false); 498 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 499 mAidRoutingManager); 500 mRegisteredAidCache.onNfcDisabled(); 501 502 verify(mAidRoutingManager).supportsAidPrefixRouting(); 503 verify(mAidRoutingManager).supportsAidSubsetRouting(); 504 verify(mAidRoutingManager).onNfccRoutingTableCleared(); 505 } 506 507 @Test testPollingLoopFilterToForeground_walletRoleEnabled_walletSet()508 public void testPollingLoopFilterToForeground_walletRoleEnabled_walletSet() { 509 setWalletRoleFlag(true); 510 supportPrefixAndSubset(false); 511 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 512 mAidRoutingManager); 513 mRegisteredAidCache.mNfcEnabled = true; 514 515 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 516 apduServiceInfos.add(createServiceInfoForAidRouting( 517 WALLET_PAYMENT_SERVICE, 518 true, 519 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 520 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 521 false, 522 false, 523 USER_ID, 524 true)); 525 apduServiceInfos.add(createServiceInfoForAidRouting( 526 FOREGROUND_SERVICE, 527 true, 528 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 529 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 530 false, 531 false, 532 USER_ID, 533 true)); 534 apduServiceInfos.add(createServiceInfoForAidRouting( 535 NON_PAYMENT_SERVICE, 536 true, 537 List.of(NON_PAYMENT_AID_1), 538 List.of(CardEmulation.CATEGORY_OTHER), 539 false, 540 false, 541 USER_ID, 542 true)); 543 544 mRegisteredAidCache.onWalletRoleHolderChanged(WALLET_HOLDER_PACKAGE_NAME, USER_ID); 545 mRegisteredAidCache.onPreferredForegroundServiceChanged(USER_ID, FOREGROUND_SERVICE); 546 547 ApduServiceInfo resolvedApdu = 548 mRegisteredAidCache.resolvePollingLoopFilterConflict(apduServiceInfos); 549 550 Assert.assertEquals(resolvedApdu, apduServiceInfos.get(1)); 551 } 552 553 @Test testPollingLoopFilterToWallet_walletRoleEnabled_walletSet()554 public void testPollingLoopFilterToWallet_walletRoleEnabled_walletSet() { 555 setWalletRoleFlag(true); 556 supportPrefixAndSubset(false); 557 mRegisteredAidCache = new RegisteredAidCache(mContext, mWalletRoleObserver, 558 mAidRoutingManager); 559 mRegisteredAidCache.mNfcEnabled = true; 560 561 List<ApduServiceInfo> apduServiceInfos = new ArrayList<>(); 562 apduServiceInfos.add(createServiceInfoForAidRouting( 563 WALLET_PAYMENT_SERVICE, 564 true, 565 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 566 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 567 false, 568 false, 569 USER_ID, 570 true)); 571 apduServiceInfos.add(createServiceInfoForAidRouting( 572 FOREGROUND_SERVICE, 573 true, 574 List.of(PAYMENT_AID_1, NON_PAYMENT_AID_1), 575 List.of(CardEmulation.CATEGORY_PAYMENT, CardEmulation.CATEGORY_OTHER), 576 false, 577 false, 578 USER_ID, 579 true)); 580 apduServiceInfos.add(createServiceInfoForAidRouting( 581 NON_PAYMENT_SERVICE, 582 true, 583 List.of(NON_PAYMENT_AID_1), 584 List.of(CardEmulation.CATEGORY_OTHER), 585 false, 586 false, 587 USER_ID, 588 true)); 589 590 mRegisteredAidCache.mDefaultWalletHolderPackageName = WALLET_HOLDER_PACKAGE_NAME; 591 592 ApduServiceInfo resolvedApdu = 593 mRegisteredAidCache.resolvePollingLoopFilterConflict(apduServiceInfos); 594 595 Assert.assertEquals(resolvedApdu, apduServiceInfos.get(0)); 596 } 597 setWalletRoleFlag(boolean flag)598 private void setWalletRoleFlag(boolean flag) { 599 when(mWalletRoleObserver.isWalletRoleFeatureEnabled()).thenReturn(flag); 600 } 601 supportPrefixAndSubset(boolean support)602 private void supportPrefixAndSubset(boolean support) { 603 when(mAidRoutingManager.supportsAidPrefixRouting()).thenReturn(support); 604 when(mAidRoutingManager.supportsAidSubsetRouting()).thenReturn(support); 605 } 606 createServiceInfoForAidRouting(ComponentName componentName, boolean onHost, List<String> aids,List<String> categories, boolean requiresUnlock, boolean requiresScreenOn, int uid, boolean isCategoryOtherServiceEnabled)607 private static ApduServiceInfo createServiceInfoForAidRouting(ComponentName componentName, 608 boolean onHost, 609 List<String> aids,List<String> categories, boolean requiresUnlock, boolean requiresScreenOn, 610 int uid, boolean isCategoryOtherServiceEnabled) { 611 ApduServiceInfo apduServiceInfo = Mockito.mock(ApduServiceInfo.class); 612 when(apduServiceInfo.isOnHost()).thenReturn(onHost); 613 when(apduServiceInfo.getAids()).thenReturn(aids); 614 when(apduServiceInfo.getUid()).thenReturn(uid); 615 when(apduServiceInfo.requiresUnlock()).thenReturn(requiresUnlock); 616 when(apduServiceInfo.requiresScreenOn()).thenReturn(requiresScreenOn); 617 when(apduServiceInfo.isCategoryOtherServiceEnabled()) 618 .thenReturn(isCategoryOtherServiceEnabled); 619 when(apduServiceInfo.getComponent()).thenReturn(componentName); 620 for (int i = 0; i < aids.size(); i++) { 621 String aid = aids.get(i); 622 String category = categories.get(i); 623 when(apduServiceInfo.getCategoryForAid(eq(aid))).thenReturn(category); 624 } 625 return apduServiceInfo; 626 } 627 628 } 629