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 com.android.nfc.cardemulation.AidRoutingManager.AID_MATCHING_EXACT_ONLY; 20 import static com.android.nfc.cardemulation.AidRoutingManager.AID_MATCHING_EXACT_OR_PREFIX; 21 import static com.android.nfc.cardemulation.AidRoutingManager.AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX; 22 import static com.android.nfc.cardemulation.AidRoutingManager.AID_MATCHING_PREFIX_ONLY; 23 import static com.android.nfc.cardemulation.AidRoutingManager.ROUTE_HOST; 24 import static com.google.common.truth.Truth.assertThat; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.anyString; 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.when; 31 32 import androidx.test.runner.AndroidJUnit4; 33 34 import com.android.dx.mockito.inline.extended.ExtendedMockito; 35 import com.android.nfc.NfcService; 36 import com.android.nfc.NfcStatsLog; 37 import com.android.nfc.cardemulation.AidRoutingManager.AidEntry; 38 39 import java.io.PrintWriter; 40 import java.util.HashMap; 41 import java.util.HashSet; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.Mockito; 49 import org.mockito.MockitoAnnotations; 50 import org.mockito.ArgumentCaptor; 51 import org.mockito.Captor; 52 import org.mockito.MockitoSession; 53 import org.mockito.quality.Strictness; 54 55 @RunWith(AndroidJUnit4.class) 56 public class AidRoutingManagerTest { 57 58 private AidRoutingManager manager; 59 private MockitoSession mStaticMockSession; 60 61 @Mock 62 private RoutingOptionManager mRoutingOptionManager; 63 @Mock 64 private NfcService mNfcService; 65 @Mock 66 private PrintWriter mPw; 67 68 @Captor 69 private ArgumentCaptor<String> unroutedAidsCaptor; 70 @Captor 71 private ArgumentCaptor<String> routedAidsCaptor; 72 @Captor 73 private ArgumentCaptor<Integer> routeCaptor; 74 @Captor 75 private ArgumentCaptor<Integer> aidTypeCaptor; 76 @Captor 77 private ArgumentCaptor<Integer> powerCaptor; 78 @Captor 79 private ArgumentCaptor<Integer> codeCaptor; 80 @Captor 81 private ArgumentCaptor<Integer> arg1Captor; 82 @Captor 83 private ArgumentCaptor<Integer> arg2Captor; 84 @Captor 85 private ArgumentCaptor<Integer> arg3Captor; 86 87 private static final int DEFAULT_ROUTE = 0; 88 private static final int OVERRIDE_DEFAULT_ROUTE = 10; 89 private static final int DEFAULT_OFFHOST_ROUTE = 20; 90 private static final int OVERRIDE_ISODEP_ROUTE = 30; 91 private static final byte[] OFFHOST_ROUTE_UICC = new byte[] {5, 6, 7, 8}; 92 private static final byte[] OFFHOST_ROUTE_ESE = new byte[] {1, 2, 3, 4}; 93 private static final int FIRST_AID_ENTRY_POWER = 1; 94 private static final int FIRST_AID_ENTRY_AID_INFO = 2; 95 private static final int SECOND_AID_ENTRY_POWER = 3; 96 private static final int SECOND_AID_ENTRY_AID_INFO = 4; 97 private static final int THIRD_AID_ENTRY_POWER = 5; 98 private static final int THIRD_AID_ENTRY_AID_INFO = 6; 99 private static final int FOURTH_AID_ENTRY_POWER = 7; 100 private static final int FOURTH_AID_ENTRY_AID_INFO = 8; 101 102 @Before setUp()103 public void setUp() { 104 mStaticMockSession = ExtendedMockito.mockitoSession() 105 .mockStatic(RoutingOptionManager.class) 106 .mockStatic(NfcService.class) 107 .mockStatic(NfcStatsLog.class) 108 .strictness(Strictness.LENIENT) 109 .startMocking(); 110 MockitoAnnotations.initMocks(this); 111 when(RoutingOptionManager.getInstance()).thenReturn(mRoutingOptionManager); 112 when(NfcService.getInstance()).thenReturn(mNfcService); 113 } 114 115 @After tearDown()116 public void tearDown() { 117 mStaticMockSession.finishMocking(); 118 } 119 120 @Test testConstructor()121 public void testConstructor() { 122 manager = new AidRoutingManager(); 123 } 124 125 @Test testSupportsAidPrefixRouting_ReturnsTrue()126 public void testSupportsAidPrefixRouting_ReturnsTrue() { 127 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_OR_PREFIX); 128 manager = new AidRoutingManager(); 129 130 boolean result = manager.supportsAidPrefixRouting(); 131 132 assertThat(result).isTrue(); 133 } 134 135 @Test testSupportsAidPrefixRouting_ReturnsFalse()136 public void testSupportsAidPrefixRouting_ReturnsFalse() { 137 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_ONLY); 138 manager = new AidRoutingManager(); 139 140 boolean result = manager.supportsAidPrefixRouting(); 141 142 assertThat(result).isFalse(); 143 } 144 145 @Test testSupportsAidSubsetRouting_ReturnsTrue()146 public void testSupportsAidSubsetRouting_ReturnsTrue() { 147 when(mRoutingOptionManager.getAidMatchingSupport()) 148 .thenReturn(AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX); 149 manager = new AidRoutingManager(); 150 151 boolean result = manager.supportsAidSubsetRouting(); 152 153 assertThat(result).isTrue(); 154 } 155 156 @Test testSupportsAidSubsetRouting_ReturnsFalse()157 public void testSupportsAidSubsetRouting_ReturnsFalse() { 158 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_OR_PREFIX); 159 manager = new AidRoutingManager(); 160 161 boolean result = manager.supportsAidSubsetRouting(); 162 163 assertThat(result).isFalse(); 164 } 165 166 @Test testCalculateAidRouteSizeWithEmptyCache()167 public void testCalculateAidRouteSizeWithEmptyCache() { 168 manager = new AidRoutingManager(); 169 170 int result = manager.calculateAidRouteSize(new HashMap<String, AidEntry>()); 171 172 assertThat(result).isEqualTo(0); 173 } 174 175 @Test testCalculateAidRouteSizeWithNonEmptyCache()176 public void testCalculateAidRouteSizeWithNonEmptyCache() { 177 String firstAidEntry = "0000000000"; 178 String secondAidEntry = "000000000000000"; 179 HashMap<String, AidEntry> cache = new HashMap<>(); 180 cache.put(firstAidEntry + "*", null); 181 cache.put(secondAidEntry, null); 182 manager = new AidRoutingManager(); 183 184 int result = manager.calculateAidRouteSize(cache); 185 186 int expected = (firstAidEntry.length() / 2) + 4 + (secondAidEntry.length() / 2) + 4; 187 assertThat(result).isEqualTo(expected); 188 } 189 190 @Test testConfigureRoutingWithEmptyMap_ReturnsFalse()191 public void testConfigureRoutingWithEmptyMap_ReturnsFalse() { 192 manager = new AidRoutingManager(); 193 194 boolean result = manager.configureRouting(/* aidMap = */ new HashMap<String, AidEntry>(), 195 /* force = */ false); 196 197 assertThat(result).isFalse(); 198 } 199 200 /** 201 * Tests the case wherein: 202 * (1) The default route (mDefaultRoute) is overridden to the value OVERRIDE_DEFAULT_ROUTE. 203 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are non-null. 204 * (3) mAidMatchingSupport is equal to AID_MATCHING_PREFIX_ONLY 205 * (4) mDefaultIsoDepRoute is equal to ROUTE_HOST (so that the default route is registered) 206 * (5) NCI Version 2 is used. 207 * 208 * Ultimately, the contents of aidMap should be committed. 209 */ 210 @Test testConfigureRoutingTestCase1_CommitsCache()211 public void testConfigureRoutingTestCase1_CommitsCache() { 212 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(true); 213 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 214 when(mRoutingOptionManager.getOverrideDefaultRoute()).thenReturn(OVERRIDE_DEFAULT_ROUTE); 215 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(OFFHOST_ROUTE_UICC); 216 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(OFFHOST_ROUTE_ESE); 217 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_PREFIX_ONLY); 218 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(ROUTE_HOST); 219 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_2_0); 220 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 221 manager = new AidRoutingManager(); 222 manager.mRouteForAid.put("first*", 0); 223 manager.mRouteForAid.put("second#", 0); 224 manager.mRouteForAid.put("third", 0); 225 226 boolean result = manager.configureRouting(getAidMap(), /* force = */ false); 227 228 assertThat(result).isTrue(); 229 verify(mNfcService, times(4)).unrouteAids(unroutedAidsCaptor.capture()); 230 assertThat(unroutedAidsCaptor.getAllValues().contains("first")).isTrue(); 231 assertThat(unroutedAidsCaptor.getAllValues().contains("second#")).isTrue(); 232 assertThat(unroutedAidsCaptor.getAllValues().contains("third")).isTrue(); 233 assertThat(unroutedAidsCaptor.getAllValues().contains("")).isTrue(); 234 verify(mNfcService, times(3)).routeAids(routedAidsCaptor.capture(), 235 routeCaptor.capture(), 236 aidTypeCaptor.capture(), 237 powerCaptor.capture()); 238 assertThat(routedAidsCaptor.getAllValues().get(0)).isEqualTo(""); 239 assertThat(routedAidsCaptor.getAllValues().get(1)).isEqualTo("firstAidEntry"); 240 assertThat(routedAidsCaptor.getAllValues().get(2)).isEqualTo("fourthAidEntry"); 241 assertThat(routeCaptor.getAllValues().get(0)).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 242 assertThat(routeCaptor.getAllValues().get(1)).isEqualTo(OFFHOST_ROUTE_ESE[1]); 243 assertThat(routeCaptor.getAllValues().get(2)).isEqualTo(OFFHOST_ROUTE_UICC[0]); 244 assertThat(aidTypeCaptor.getAllValues().get(0)) 245 .isEqualTo(RegisteredAidCache.AID_ROUTE_QUAL_PREFIX); 246 assertThat(aidTypeCaptor.getAllValues().get(1)).isEqualTo(FIRST_AID_ENTRY_AID_INFO); 247 assertThat(aidTypeCaptor.getAllValues().get(2)).isEqualTo(FOURTH_AID_ENTRY_AID_INFO); 248 assertThat(powerCaptor.getAllValues().get(0)).isEqualTo(RegisteredAidCache.POWER_STATE_ALL); 249 assertThat(powerCaptor.getAllValues().get(1)).isEqualTo(FIRST_AID_ENTRY_POWER); 250 assertThat(powerCaptor.getAllValues().get(2)).isEqualTo(FOURTH_AID_ENTRY_POWER); 251 verify(mNfcService).commitRouting(); 252 assertThat(manager.mDefaultRoute).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 253 assertThat(manager.mRouteForAid.size()).isEqualTo(3); 254 assertThat(manager.mPowerForAid.size()).isEqualTo(3); 255 assertThat(manager.mAidRoutingTable.size()).isEqualTo(3); 256 } 257 258 /** 259 * Tests the case wherein: 260 * (1) The default route (mDefaultRoute) is unmodified (DEFAULT_ROUTE). 261 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are non-null. 262 * (3) mAidMatchingSupport is equal to AID_MATCHING_PREFIX_ONLY 263 * (4) mDefaultIsoDepRoute is equal to ROUTE_HOST (so that the default route is registered) 264 * (5) NCI Version 1 is used. 265 * 266 * Ultimately, nothing is committed and an error message is written to NfcStatsLog. 267 */ 268 @Test testConfigureRoutingTestCase2_WritesError()269 public void testConfigureRoutingTestCase2_WritesError() { 270 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(false); 271 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 272 when(mRoutingOptionManager.getDefaultRoute()).thenReturn(DEFAULT_ROUTE); 273 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(OFFHOST_ROUTE_UICC); 274 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(OFFHOST_ROUTE_ESE); 275 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_PREFIX_ONLY); 276 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(ROUTE_HOST); 277 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_1_0); 278 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 279 manager = new AidRoutingManager(); 280 281 boolean result = manager.configureRouting(getAidMap(), /* force = */ false); 282 283 assertThat(result).isTrue(); 284 verify(mNfcService, never()).unrouteAids(anyString()); 285 verify(mNfcService, never()).routeAids(anyString(), anyInt(), anyInt(), anyInt()); 286 verify(mNfcService, never()).commitRouting(); 287 ExtendedMockito.verify(() -> NfcStatsLog.write(codeCaptor.capture(), 288 arg1Captor.capture(), 289 arg2Captor.capture(), 290 arg3Captor.capture())); 291 assertThat(codeCaptor.getValue()).isEqualTo(NfcStatsLog.NFC_ERROR_OCCURRED); 292 assertThat(arg1Captor.getValue()).isEqualTo(NfcStatsLog.NFC_ERROR_OCCURRED__TYPE__AID_OVERFLOW); 293 assertThat(arg2Captor.getValue()).isEqualTo(0); 294 assertThat(arg3Captor.getValue()).isEqualTo(0); 295 assertThat(manager.mDefaultRoute).isEqualTo(OFFHOST_ROUTE_ESE[1]); 296 assertThat(manager.mRouteForAid.size()).isEqualTo(3); 297 assertThat(manager.mPowerForAid.size()).isEqualTo(3); 298 assertThat(manager.mAidRoutingTable.size()).isEqualTo(3); 299 } 300 301 /** 302 * Tests the case wherein: 303 * (1) The default route (mDefaultRoute) is unmodified (DEFAULT_ROUTE). 304 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are non-null. 305 * (3) mAidMatchingSupport is equal to AID_MATCHING_ONLY 306 * (4) mDefaultIsoDepRoute is equal to OVERRIDE_ISODEP_ROUTE (so that the default route is not 307 * registered) 308 * (5) NCI Version 2 is used. 309 * 310 * Ultimately, the routing table is not updated and no other action is taken. 311 */ 312 @Test testConfigureRoutingTestCase3_DoNothing()313 public void testConfigureRoutingTestCase3_DoNothing() { 314 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(false); 315 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 316 when(mRoutingOptionManager.getDefaultRoute()).thenReturn(DEFAULT_ROUTE); 317 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(OFFHOST_ROUTE_UICC); 318 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(OFFHOST_ROUTE_ESE); 319 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_ONLY); 320 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(OVERRIDE_ISODEP_ROUTE); 321 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_1_0); 322 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 323 manager = new AidRoutingManager(); 324 manager.mRouteForAid.put("first*", 0); 325 manager.mRouteForAid.put("second#", 0); 326 manager.mRouteForAid.put("third", 0); 327 // Create a HashMap with only one AidEntry 328 HashMap<String, AidEntry> aidMap = new HashMap<>(); 329 AidEntry aidEntry = manager.new AidEntry(); 330 aidEntry.isOnHost = false; 331 aidEntry.offHostSE = "eSE2"; 332 aidEntry.power = 1; 333 aidEntry.aidInfo = 2; 334 aidMap.put("firstAidEntry*", aidEntry); 335 336 boolean result = manager.configureRouting(aidMap, /* force = */ false); 337 338 assertThat(result).isTrue(); 339 340 verify(mNfcService, times(3)).unrouteAids(unroutedAidsCaptor.capture()); 341 assertThat(unroutedAidsCaptor.getAllValues().contains("first*")).isTrue(); 342 assertThat(unroutedAidsCaptor.getAllValues().contains("second#")).isTrue(); 343 assertThat(unroutedAidsCaptor.getAllValues().contains("third")).isTrue(); 344 ExtendedMockito.verify(() -> 345 NfcStatsLog.write(anyInt(), anyInt(), anyInt(), anyInt()), times(0)); 346 assertThat(manager.mDefaultRoute).isEqualTo(DEFAULT_ROUTE); 347 assertThat(manager.mRouteForAid.size()).isEqualTo(1); 348 assertThat(manager.mPowerForAid.size()).isEqualTo(1); 349 assertThat(manager.mAidRoutingTable.size()).isEqualTo(1); 350 } 351 352 /** 353 * Tests the case wherein: 354 * (1) The default route (mDefaultRoute) is unmodified (DEFAULT_ROUTE). 355 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are non-null. 356 * (3) mAidMatchingSupport is equal to AID_MATCHING_ONLY 357 * (4) mDefaultIsoDepRoute is equal to OVERRIDE_ISODEP_ROUTE (so that the default route is not 358 * registered) 359 * (5) NCI Version 2 is used. 360 * 361 * This case is identical to Test Case 3, with the exception of the value of the force variable, 362 * which causes the cache to be committed. 363 */ 364 @Test testConfigureRoutingTestCase4_CommitsCache()365 public void testConfigureRoutingTestCase4_CommitsCache() { 366 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(false); 367 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 368 when(mRoutingOptionManager.getDefaultRoute()).thenReturn(DEFAULT_ROUTE); 369 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(OFFHOST_ROUTE_UICC); 370 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(OFFHOST_ROUTE_ESE); 371 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_ONLY); 372 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(OVERRIDE_ISODEP_ROUTE); 373 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_1_0); 374 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 375 manager = new AidRoutingManager(); 376 manager.mRouteForAid.put("first*", 0); 377 manager.mRouteForAid.put("second#", 0); 378 manager.mRouteForAid.put("third", 0); 379 // Create a HashMap with only one AidEntry 380 HashMap<String, AidEntry> aidMap = new HashMap<>(); 381 AidEntry aidEntry = manager.new AidEntry(); 382 aidEntry.isOnHost = false; 383 aidEntry.offHostSE = "eSE2"; 384 aidEntry.power = 1; 385 aidEntry.aidInfo = 2; 386 aidMap.put("firstAidEntry*", aidEntry); 387 388 boolean result = manager.configureRouting(aidMap, /* force = */ true); 389 390 assertThat(result).isTrue(); 391 verify(mNfcService).commitRouting(); 392 } 393 394 /** 395 * Tests the case wherein: 396 * (1) The default route (mDefaultRoute) is overridden to the value OVERRIDE_DEFAULT_ROUTE. 397 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are null. 398 * (3) mAidMatchingSupport is equal to AID_MATCHING_EXACT_OR_PREFIX 399 * (4) mDefaultIsoDepRoute is equal to ROUTE_HOST (so that the default route is registered) 400 * (5) NCI Version 2 is used. 401 * 402 * Ultimately, the contents of aidMap should be committed. 403 */ 404 @Test testConfigureRoutingTestCase5_CommitsCache()405 public void testConfigureRoutingTestCase5_CommitsCache() { 406 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(true); 407 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 408 when(mRoutingOptionManager.getOverrideDefaultRoute()).thenReturn(OVERRIDE_DEFAULT_ROUTE); 409 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(null); 410 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(null); 411 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_EXACT_OR_PREFIX); 412 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(ROUTE_HOST); 413 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_2_0); 414 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 415 manager = new AidRoutingManager(); 416 manager.mRouteForAid.put("first*", 0); 417 manager.mRouteForAid.put("second#", 0); 418 manager.mRouteForAid.put("third", 0); 419 420 boolean result = manager.configureRouting(getAidMap(), /* force = */ false); 421 422 assertThat(result).isTrue(); 423 verify(mNfcService, times(4)).unrouteAids(unroutedAidsCaptor.capture()); 424 assertThat(unroutedAidsCaptor.getAllValues().contains("first")).isTrue(); 425 assertThat(unroutedAidsCaptor.getAllValues().contains("second#")).isTrue(); 426 assertThat(unroutedAidsCaptor.getAllValues().contains("third")).isTrue(); 427 assertThat(unroutedAidsCaptor.getAllValues().contains("")).isTrue(); 428 verify(mNfcService, times(4)).routeAids(routedAidsCaptor.capture(), 429 routeCaptor.capture(), 430 aidTypeCaptor.capture(), 431 powerCaptor.capture()); 432 assertThat(routedAidsCaptor.getAllValues().get(0)).isEqualTo(""); 433 assertThat(routedAidsCaptor.getAllValues().get(1)).isEqualTo("fourthAidEntry"); 434 assertThat(routedAidsCaptor.getAllValues().get(2)).isEqualTo("thirdAidEntry"); 435 assertThat(routedAidsCaptor.getAllValues().get(3)).isEqualTo("firstAidEntry"); 436 assertThat(routeCaptor.getAllValues().get(0)).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 437 assertThat(routeCaptor.getAllValues().get(1)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 438 assertThat(routeCaptor.getAllValues().get(2)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 439 assertThat(routeCaptor.getAllValues().get(3)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 440 assertThat(aidTypeCaptor.getAllValues().get(0)) 441 .isEqualTo(RegisteredAidCache.AID_ROUTE_QUAL_PREFIX); 442 assertThat(aidTypeCaptor.getAllValues().get(1)).isEqualTo(FOURTH_AID_ENTRY_AID_INFO); 443 assertThat(aidTypeCaptor.getAllValues().get(2)).isEqualTo(THIRD_AID_ENTRY_AID_INFO); 444 assertThat(aidTypeCaptor.getAllValues().get(3)).isEqualTo(FIRST_AID_ENTRY_AID_INFO); 445 assertThat(powerCaptor.getAllValues().get(0)).isEqualTo(RegisteredAidCache.POWER_STATE_ALL); 446 assertThat(powerCaptor.getAllValues().get(1)).isEqualTo(FOURTH_AID_ENTRY_POWER); 447 assertThat(powerCaptor.getAllValues().get(2)).isEqualTo(THIRD_AID_ENTRY_POWER); 448 assertThat(powerCaptor.getAllValues().get(3)).isEqualTo(FIRST_AID_ENTRY_POWER); 449 verify(mNfcService).commitRouting(); 450 assertThat(manager.mDefaultRoute).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 451 assertThat(manager.mRouteForAid.size()).isEqualTo(4); 452 assertThat(manager.mPowerForAid.size()).isEqualTo(4); 453 assertThat(manager.mAidRoutingTable.size()).isEqualTo(2); 454 } 455 456 /** 457 * Tests the case wherein: 458 * (1) The default route (mDefaultRoute) is overridden to the value OVERRIDE_DEFAULT_ROUTE. 459 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are null. 460 * (3) mAidMatchingSupport is equal to AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX 461 * (4) mDefaultIsoDepRoute is equal to ROUTE_HOST (so that the default route is registered) 462 * (5) NCI Version 2 is used. 463 * 464 * Ultimately, the contents of aidMap should be committed. 465 */ 466 @Test testConfigureRoutingTestCase6_CommitsCache()467 public void testConfigureRoutingTestCase6_CommitsCache() { 468 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(true); 469 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 470 when(mRoutingOptionManager.getOverrideDefaultRoute()).thenReturn(OVERRIDE_DEFAULT_ROUTE); 471 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(null); 472 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(null); 473 when(mRoutingOptionManager.getAidMatchingSupport()) 474 .thenReturn(AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX); 475 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(ROUTE_HOST); 476 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_2_0); 477 when(mNfcService.getAidRoutingTableSize()).thenReturn(0); 478 manager = new AidRoutingManager(); 479 manager.mRouteForAid.put("first*", 0); 480 manager.mRouteForAid.put("second#", 0); 481 manager.mRouteForAid.put("third", 0); 482 483 boolean result = manager.configureRouting(getAidMap(), /* force = */ false); 484 485 assertThat(result).isTrue(); 486 verify(mNfcService, times(4)).unrouteAids(unroutedAidsCaptor.capture()); 487 assertThat(unroutedAidsCaptor.getAllValues().contains("first")).isTrue(); 488 assertThat(unroutedAidsCaptor.getAllValues().contains("second")).isTrue(); 489 assertThat(unroutedAidsCaptor.getAllValues().contains("third")).isTrue(); 490 assertThat(unroutedAidsCaptor.getAllValues().contains("")).isTrue(); 491 verify(mNfcService, times(5)).routeAids(routedAidsCaptor.capture(), 492 routeCaptor.capture(), 493 aidTypeCaptor.capture(), 494 powerCaptor.capture()); 495 assertThat(routedAidsCaptor.getAllValues().get(0)).isEqualTo(""); 496 assertThat(routedAidsCaptor.getAllValues().get(1)).isEqualTo("secondAidEntry"); 497 assertThat(routedAidsCaptor.getAllValues().get(2)).isEqualTo("fourthAidEntry"); 498 assertThat(routedAidsCaptor.getAllValues().get(3)).isEqualTo("thirdAidEntry"); 499 assertThat(routedAidsCaptor.getAllValues().get(4)).isEqualTo("firstAidEntry"); 500 assertThat(routeCaptor.getAllValues().get(0)).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 501 assertThat(routeCaptor.getAllValues().get(1)).isEqualTo(DEFAULT_ROUTE); 502 assertThat(routeCaptor.getAllValues().get(2)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 503 assertThat(routeCaptor.getAllValues().get(3)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 504 assertThat(routeCaptor.getAllValues().get(4)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 505 assertThat(aidTypeCaptor.getAllValues().get(0)) 506 .isEqualTo(RegisteredAidCache.AID_ROUTE_QUAL_PREFIX); 507 assertThat(aidTypeCaptor.getAllValues().get(1)).isEqualTo(SECOND_AID_ENTRY_AID_INFO); 508 assertThat(aidTypeCaptor.getAllValues().get(2)).isEqualTo(FOURTH_AID_ENTRY_AID_INFO); 509 assertThat(aidTypeCaptor.getAllValues().get(3)).isEqualTo(THIRD_AID_ENTRY_AID_INFO); 510 assertThat(aidTypeCaptor.getAllValues().get(4)).isEqualTo(FIRST_AID_ENTRY_AID_INFO); 511 assertThat(powerCaptor.getAllValues().get(0)).isEqualTo(RegisteredAidCache.POWER_STATE_ALL); 512 assertThat(powerCaptor.getAllValues().get(1)).isEqualTo(SECOND_AID_ENTRY_POWER); 513 assertThat(powerCaptor.getAllValues().get(2)).isEqualTo(FOURTH_AID_ENTRY_POWER); 514 assertThat(powerCaptor.getAllValues().get(3)).isEqualTo(THIRD_AID_ENTRY_POWER); 515 assertThat(powerCaptor.getAllValues().get(4)).isEqualTo(FIRST_AID_ENTRY_POWER); 516 verify(mNfcService).commitRouting(); 517 assertThat(manager.mDefaultRoute).isEqualTo(OVERRIDE_DEFAULT_ROUTE); 518 assertThat(manager.mRouteForAid.size()).isEqualTo(4); 519 assertThat(manager.mPowerForAid.size()).isEqualTo(4); 520 assertThat(manager.mAidRoutingTable.size()).isEqualTo(2); 521 } 522 523 /** 524 * Tests the case wherein: 525 * (1) The default route (mDefaultRoute) is unmodified (DEFAULT_ROUTE). 526 * (2) Both mOffHostRouteUicc and mOffHostRouteEse are null. 527 * (3) mAidMatchingSupport is equal to AID_MATCHING_PREFIX_ONLY 528 * (4) mDefaultIsoDepRoute is equal to ROUTE_HOST (so that the default route is registered) 529 * (5) NCI Version 1 is used. 530 * 531 * Ultimately, due to the value of mAidRoutingTableSize, the contents of the cache are committed. 532 */ 533 @Test testConfigureRoutingTestCase7_CommitsCache()534 public void testConfigureRoutingTestCase7_CommitsCache() { 535 when(mRoutingOptionManager.isRoutingTableOverrided()).thenReturn(false); 536 when(mRoutingOptionManager.getDefaultOffHostRoute()).thenReturn(DEFAULT_OFFHOST_ROUTE); 537 when(mRoutingOptionManager.getDefaultRoute()).thenReturn(DEFAULT_ROUTE); 538 when(mRoutingOptionManager.getOffHostRouteUicc()).thenReturn(null); 539 when(mRoutingOptionManager.getOffHostRouteEse()).thenReturn(null); 540 when(mRoutingOptionManager.getAidMatchingSupport()).thenReturn(AID_MATCHING_PREFIX_ONLY); 541 when(mRoutingOptionManager.getDefaultIsoDepRoute()).thenReturn(ROUTE_HOST); 542 when(mNfcService.getNciVersion()).thenReturn(NfcService.NCI_VERSION_1_0); 543 when(mNfcService.getAidRoutingTableSize()).thenReturn(100); 544 manager = new AidRoutingManager(); 545 546 boolean result = manager.configureRouting(getAidMap(), /* force = */ false); 547 548 assertThat(result).isTrue(); 549 verify(mNfcService, never()).unrouteAids(anyString()); 550 verify(mNfcService, times(3)).routeAids(routedAidsCaptor.capture(), 551 routeCaptor.capture(), 552 aidTypeCaptor.capture(), 553 powerCaptor.capture()); 554 assertThat(routedAidsCaptor.getAllValues().get(0)).isEqualTo("fourthAidEntry"); 555 assertThat(routedAidsCaptor.getAllValues().get(1)).isEqualTo("firstAidEntry"); 556 assertThat(routedAidsCaptor.getAllValues().get(2)).isEqualTo("thirdAidEntry"); 557 assertThat(routeCaptor.getAllValues().get(0)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 558 assertThat(routeCaptor.getAllValues().get(1)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 559 assertThat(routeCaptor.getAllValues().get(2)).isEqualTo(DEFAULT_OFFHOST_ROUTE); 560 assertThat(aidTypeCaptor.getAllValues().get(0)).isEqualTo(FOURTH_AID_ENTRY_AID_INFO); 561 assertThat(aidTypeCaptor.getAllValues().get(1)).isEqualTo(FIRST_AID_ENTRY_AID_INFO); 562 assertThat(aidTypeCaptor.getAllValues().get(2)).isEqualTo(THIRD_AID_ENTRY_AID_INFO); 563 assertThat(powerCaptor.getAllValues().get(0)).isEqualTo(FOURTH_AID_ENTRY_POWER); 564 assertThat(powerCaptor.getAllValues().get(1)).isEqualTo(FIRST_AID_ENTRY_POWER); 565 assertThat(powerCaptor.getAllValues().get(2)).isEqualTo(THIRD_AID_ENTRY_POWER); 566 verify(mNfcService).commitRouting(); 567 assertThat(manager.mDefaultRoute).isEqualTo(DEFAULT_ROUTE); 568 assertThat(manager.mRouteForAid.size()).isEqualTo(4); 569 assertThat(manager.mPowerForAid.size()).isEqualTo(4); 570 assertThat(manager.mAidRoutingTable.size()).isEqualTo(2); 571 } 572 573 @Test testOnNfccRoutingTableCleared()574 public void testOnNfccRoutingTableCleared() { 575 manager = new AidRoutingManager(); 576 manager.mAidRoutingTable.put(0, new HashSet<String>()); 577 manager.mRouteForAid.put("", 0); 578 manager.mPowerForAid.put("", 0); 579 580 manager.onNfccRoutingTableCleared(); 581 582 assertThat(manager.mAidRoutingTable.size()).isEqualTo(0); 583 assertThat(manager.mRouteForAid.isEmpty()).isTrue(); 584 assertThat(manager.mPowerForAid.isEmpty()).isTrue(); 585 } 586 587 @Test testDump()588 public void testDump() { 589 manager = new AidRoutingManager(); 590 HashSet<String> routingTableSet = new HashSet<>(); 591 routingTableSet.add(""); 592 manager.mAidRoutingTable.put(0, routingTableSet); 593 594 manager.dump(/* fd = */ null, mPw, /* args = */ null); 595 596 verify(mPw, times(4)).println(anyString()); 597 } 598 getAidMap()599 private HashMap<String, AidEntry> getAidMap() { 600 HashMap<String, AidEntry> aidMap = new HashMap<>(); 601 AidEntry firstAidEntry = manager.new AidEntry(); 602 firstAidEntry.isOnHost = false; 603 firstAidEntry.offHostSE = "eSE2"; 604 firstAidEntry.power = FIRST_AID_ENTRY_POWER; 605 firstAidEntry.aidInfo = FIRST_AID_ENTRY_AID_INFO; 606 aidMap.put("firstAidEntry*", firstAidEntry); 607 608 AidEntry secondAidEntry = manager.new AidEntry(); 609 secondAidEntry.isOnHost = true; 610 secondAidEntry.power = SECOND_AID_ENTRY_POWER; 611 secondAidEntry.aidInfo = SECOND_AID_ENTRY_AID_INFO; 612 aidMap.put("secondAidEntry#", secondAidEntry); 613 614 AidEntry thirdAidEntry = manager.new AidEntry(); 615 thirdAidEntry.isOnHost = false; 616 thirdAidEntry.offHostSE = "invalid SE"; 617 thirdAidEntry.power = THIRD_AID_ENTRY_POWER; 618 thirdAidEntry.aidInfo = THIRD_AID_ENTRY_AID_INFO; 619 aidMap.put("thirdAidEntry", thirdAidEntry); 620 621 AidEntry fourthAidEntry = manager.new AidEntry(); 622 fourthAidEntry.isOnHost = false; 623 fourthAidEntry.offHostSE = "SIM1"; 624 fourthAidEntry.power = FOURTH_AID_ENTRY_POWER; 625 fourthAidEntry.aidInfo = FOURTH_AID_ENTRY_AID_INFO; 626 aidMap.put("fourthAidEntry", fourthAidEntry); 627 628 return aidMap; 629 } 630 }