1 /* 2 * Copyright 2020 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.google.android.iwlan.epdg; 18 19 import static android.net.DnsResolver.TYPE_A; 20 import static android.net.DnsResolver.TYPE_AAAA; 21 22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 23 24 import static org.junit.Assert.*; 25 import static org.mockito.Mockito.*; 26 27 import static java.util.stream.Collectors.toList; 28 29 import android.content.Context; 30 import android.content.SharedPreferences; 31 import android.net.DnsResolver; 32 import android.net.InetAddresses; 33 import android.net.Network; 34 import android.os.Handler; 35 import android.os.Looper; 36 import android.os.PersistableBundle; 37 import android.telephony.CarrierConfigManager; 38 import android.telephony.CellIdentityGsm; 39 import android.telephony.CellIdentityLte; 40 import android.telephony.CellIdentityNr; 41 import android.telephony.CellIdentityWcdma; 42 import android.telephony.CellInfo; 43 import android.telephony.CellInfoGsm; 44 import android.telephony.CellInfoLte; 45 import android.telephony.CellInfoNr; 46 import android.telephony.CellInfoWcdma; 47 import android.telephony.SubscriptionInfo; 48 import android.telephony.SubscriptionManager; 49 import android.telephony.TelephonyManager; 50 import android.util.Log; 51 52 import com.google.android.iwlan.ErrorPolicyManager; 53 import com.google.android.iwlan.IwlanError; 54 55 import org.junit.After; 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.mockito.Mock; 59 import org.mockito.MockitoAnnotations; 60 import org.mockito.MockitoSession; 61 import org.mockito.invocation.InvocationOnMock; 62 import org.mockito.stubbing.Answer; 63 64 import java.net.InetAddress; 65 import java.net.UnknownHostException; 66 import java.util.*; 67 import java.util.concurrent.CountDownLatch; 68 import java.util.concurrent.Executor; 69 import java.util.concurrent.TimeUnit; 70 71 public class EpdgSelectorTest { 72 private static final String TAG = "EpdgSelectorTest"; 73 private EpdgSelector mEpdgSelector; 74 public static final int DEFAULT_SLOT_INDEX = 0; 75 76 private static final String TEST_IP_ADDRESS = "127.0.0.1"; 77 private static final String TEST_IP_ADDRESS_1 = "127.0.0.2"; 78 private static final String TEST_IP_ADDRESS_2 = "127.0.0.3"; 79 private static final String TEST_IP_ADDRESS_3 = "127.0.0.4"; 80 private static final String TEST_IP_ADDRESS_4 = "127.0.0.5"; 81 private static final String TEST_IP_ADDRESS_5 = "127.0.0.6"; 82 private static final String TEST_IPV6_ADDRESS = "0000:0000:0000:0000:0000:0000:0000:0001"; 83 84 private static int testPcoIdIPv6 = 0xFF01; 85 private static int testPcoIdIPv4 = 0xFF02; 86 87 private String testPcoString = "testPcoData"; 88 private byte[] pcoData = testPcoString.getBytes(); 89 private List<String> ehplmnList = new ArrayList<String>(); 90 91 @Mock private Context mMockContext; 92 @Mock private Network mMockNetwork; 93 @Mock private ErrorPolicyManager mMockErrorPolicyManager; 94 @Mock private SubscriptionManager mMockSubscriptionManager; 95 @Mock private SubscriptionInfo mMockSubscriptionInfo; 96 @Mock private CarrierConfigManager mMockCarrierConfigManager; 97 @Mock private TelephonyManager mMockTelephonyManager; 98 @Mock private SharedPreferences mMockSharedPreferences; 99 @Mock private CellInfoGsm mMockCellInfoGsm; 100 @Mock private CellIdentityGsm mMockCellIdentityGsm; 101 @Mock private CellInfoWcdma mMockCellInfoWcdma; 102 @Mock private CellIdentityWcdma mMockCellIdentityWcdma; 103 @Mock private CellInfoLte mMockCellInfoLte; 104 @Mock private CellIdentityLte mMockCellIdentityLte; 105 @Mock private CellInfoNr mMockCellInfoNr; 106 @Mock private CellIdentityNr mMockCellIdentityNr; 107 @Mock private DnsResolver mMockDnsResolver; 108 109 private PersistableBundle mTestBundle; 110 private FakeDns mFakeDns; 111 MockitoSession mStaticMockSession; 112 113 @Before setUp()114 public void setUp() throws Exception { 115 MockitoAnnotations.initMocks(this); 116 mStaticMockSession = 117 mockitoSession() 118 .mockStatic(DnsResolver.class) 119 .mockStatic(ErrorPolicyManager.class) 120 .startMocking(); 121 122 when(ErrorPolicyManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX)) 123 .thenReturn(mMockErrorPolicyManager); 124 mEpdgSelector = new EpdgSelector(mMockContext, DEFAULT_SLOT_INDEX); 125 126 when(mMockContext.getSystemService(eq(SubscriptionManager.class))) 127 .thenReturn(mMockSubscriptionManager); 128 129 when(mMockSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(anyInt())) 130 .thenReturn(mMockSubscriptionInfo); 131 132 when(mMockSubscriptionInfo.getMccString()).thenReturn("311"); 133 134 when(mMockSubscriptionInfo.getMncString()).thenReturn("120"); 135 136 when(mMockContext.getSystemService(eq(TelephonyManager.class))) 137 .thenReturn(mMockTelephonyManager); 138 139 when(mMockTelephonyManager.createForSubscriptionId(anyInt())) 140 .thenReturn(mMockTelephonyManager); 141 142 ehplmnList.add("300120"); 143 when(mMockTelephonyManager.getEquivalentHomePlmns()).thenReturn(ehplmnList); 144 145 when(mMockTelephonyManager.getSimCountryIso()).thenReturn("ca"); 146 147 when(mMockContext.getSharedPreferences(anyString(), anyInt())) 148 .thenReturn(mMockSharedPreferences); 149 150 when(mMockSharedPreferences.getString(any(), any())).thenReturn("US"); 151 152 // Mock carrier configs with test bundle 153 mTestBundle = new PersistableBundle(); 154 when(mMockContext.getSystemService(eq(CarrierConfigManager.class))) 155 .thenReturn(mMockCarrierConfigManager); 156 when(mMockCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mTestBundle); 157 158 lenient().when(DnsResolver.getInstance()).thenReturn(mMockDnsResolver); 159 160 mFakeDns = new FakeDns(); 161 mFakeDns.startMocking(); 162 } 163 164 @After cleanUp()165 public void cleanUp() throws Exception { 166 mStaticMockSession.finishMocking(); 167 mFakeDns.clearAll(); 168 } 169 170 @Test testStaticMethodPass()171 public void testStaticMethodPass() throws Exception { 172 // Set DnsResolver query mock 173 final String testStaticAddress = "epdg.epc.mnc088.mcc888.pub.3gppnetwork.org"; 174 mFakeDns.setAnswer(testStaticAddress, new String[] {TEST_IP_ADDRESS}, TYPE_A); 175 176 // Set carrier config mock 177 mTestBundle.putIntArray( 178 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 179 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_STATIC}); 180 mTestBundle.putString( 181 CarrierConfigManager.Iwlan.KEY_EPDG_STATIC_ADDRESS_STRING, testStaticAddress); 182 183 ArrayList<InetAddress> testInetAddresses = 184 getValidatedServerListWithDefaultParams(false /*isEmergency*/); 185 186 InetAddress expectedAddress = InetAddress.getByName(TEST_IP_ADDRESS); 187 188 assertEquals(testInetAddresses.size(), 1); 189 assertEquals(testInetAddresses.get(0), expectedAddress); 190 } 191 192 @Test testRoamStaticMethodPass()193 public void testRoamStaticMethodPass() throws Exception { 194 // Set DnsResolver query mock 195 final String testRoamStaticAddress = "epdg.epc.mnc088.mcc888.pub.3gppnetwork.org"; 196 mFakeDns.setAnswer(testRoamStaticAddress, new String[] {TEST_IP_ADDRESS}, TYPE_A); 197 198 // Set carrier config mock 199 mTestBundle.putIntArray( 200 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 201 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_STATIC}); 202 mTestBundle.putString( 203 CarrierConfigManager.Iwlan.KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, 204 testRoamStaticAddress); 205 206 ArrayList<InetAddress> testInetAddresses = 207 getValidatedServerListWithDefaultParams(false /*isEmergency*/); 208 209 InetAddress expectedAddress = InetAddress.getByName(TEST_IP_ADDRESS); 210 211 assertEquals(testInetAddresses.size(), 1); 212 assertEquals(testInetAddresses.get(0), expectedAddress); 213 } 214 215 @Test testPlmnResolutionMethod()216 public void testPlmnResolutionMethod() throws Exception { 217 testPlmnResolutionMethod(false); 218 } 219 220 @Test testPlmnResolutionMethodForEmergency()221 public void testPlmnResolutionMethodForEmergency() throws Exception { 222 testPlmnResolutionMethod(true); 223 } 224 225 @Test testPlmnResolutionMethodWithNoPlmnInCarrierConfig()226 public void testPlmnResolutionMethodWithNoPlmnInCarrierConfig() throws Exception { 227 // setUp() fills default values for mcc-mnc 228 String expectedFqdn1 = "epdg.epc.mnc120.mcc311.pub.3gppnetwork.org"; 229 String expectedFqdn2 = "epdg.epc.mnc120.mcc300.pub.3gppnetwork.org"; 230 231 mFakeDns.setAnswer(expectedFqdn1, new String[] {TEST_IP_ADDRESS_1}, TYPE_A); 232 mFakeDns.setAnswer(expectedFqdn2, new String[] {TEST_IP_ADDRESS_2}, TYPE_A); 233 234 ArrayList<InetAddress> testInetAddresses = 235 getValidatedServerListWithDefaultParams(false /*isEmergency*/); 236 237 assertEquals(testInetAddresses.size(), 2); 238 assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IP_ADDRESS_1))); 239 assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IP_ADDRESS_2))); 240 } 241 testPlmnResolutionMethod(boolean isEmergency)242 private void testPlmnResolutionMethod(boolean isEmergency) throws Exception { 243 String expectedFqdnFromHplmn = "epdg.epc.mnc120.mcc311.pub.3gppnetwork.org"; 244 String expectedFqdnFromEHplmn = "epdg.epc.mnc120.mcc300.pub.3gppnetwork.org"; 245 String expectedFqdnFromConfig = "epdg.epc.mnc480.mcc310.pub.3gppnetwork.org"; 246 247 mTestBundle.putIntArray( 248 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 249 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_PLMN}); 250 mTestBundle.putStringArray( 251 CarrierConfigManager.Iwlan.KEY_MCC_MNCS_STRING_ARRAY, 252 new String[] {"310-480", "300-120", "311-120"}); 253 254 mFakeDns.setAnswer(expectedFqdnFromHplmn, new String[] {TEST_IP_ADDRESS}, TYPE_A); 255 mFakeDns.setAnswer(expectedFqdnFromEHplmn, new String[] {TEST_IP_ADDRESS_1}, TYPE_A); 256 mFakeDns.setAnswer(expectedFqdnFromConfig, new String[] {TEST_IP_ADDRESS_2}, TYPE_A); 257 mFakeDns.setAnswer( 258 "sos." + expectedFqdnFromHplmn, new String[] {TEST_IP_ADDRESS_3}, TYPE_A); 259 mFakeDns.setAnswer( 260 "sos." + expectedFqdnFromEHplmn, new String[] {TEST_IP_ADDRESS_4}, TYPE_A); 261 mFakeDns.setAnswer( 262 "sos." + expectedFqdnFromConfig, new String[] {TEST_IP_ADDRESS_5}, TYPE_A); 263 264 ArrayList<InetAddress> testInetAddresses = 265 getValidatedServerListWithDefaultParams(isEmergency); 266 267 if (isEmergency) { 268 assertEquals(6, testInetAddresses.size()); 269 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_3), testInetAddresses.get(0)); 270 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS), testInetAddresses.get(1)); 271 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_4), testInetAddresses.get(2)); 272 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_1), testInetAddresses.get(3)); 273 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_5), testInetAddresses.get(4)); 274 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_2), testInetAddresses.get(5)); 275 } else { 276 assertEquals(3, testInetAddresses.size()); 277 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS), testInetAddresses.get(0)); 278 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_1), testInetAddresses.get(1)); 279 assertEquals(InetAddress.getByName(TEST_IP_ADDRESS_2), testInetAddresses.get(2)); 280 } 281 } 282 283 @Test testCarrierConfigStaticAddressList()284 public void testCarrierConfigStaticAddressList() throws Exception { 285 // Set Network.getAllByName mock 286 final String addr1 = "epdg.epc.mnc480.mcc310.pub.3gppnetwork.org"; 287 final String addr2 = "epdg.epc.mnc120.mcc300.pub.3gppnetwork.org"; 288 final String addr3 = "epdg.epc.mnc120.mcc311.pub.3gppnetwork.org"; 289 final String testStaticAddress = addr1 + "," + addr2 + "," + addr3; 290 291 mFakeDns.setAnswer(addr1, new String[] {TEST_IP_ADDRESS_1}, TYPE_A); 292 mFakeDns.setAnswer(addr2, new String[] {TEST_IP_ADDRESS_2}, TYPE_A); 293 mFakeDns.setAnswer(addr3, new String[] {TEST_IP_ADDRESS}, TYPE_A); 294 295 // Set carrier config mock 296 mTestBundle.putIntArray( 297 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 298 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_STATIC}); 299 mTestBundle.putString( 300 CarrierConfigManager.Iwlan.KEY_EPDG_STATIC_ADDRESS_STRING, testStaticAddress); 301 302 ArrayList<InetAddress> testInetAddresses = 303 getValidatedServerListWithDefaultParams(false /*isEmergency*/); 304 305 assertEquals(testInetAddresses.size(), 3); 306 assertEquals(testInetAddresses.get(0), InetAddress.getByName(TEST_IP_ADDRESS_1)); 307 assertEquals(testInetAddresses.get(1), InetAddress.getByName(TEST_IP_ADDRESS_2)); 308 assertEquals(testInetAddresses.get(2), InetAddress.getByName(TEST_IP_ADDRESS)); 309 } 310 getValidatedServerListWithDefaultParams(boolean isEmergency)311 private ArrayList<InetAddress> getValidatedServerListWithDefaultParams(boolean isEmergency) 312 throws Exception { 313 ArrayList<InetAddress> testInetAddresses = new ArrayList<InetAddress>(); 314 final CountDownLatch latch = new CountDownLatch(1); 315 IwlanError ret = 316 mEpdgSelector.getValidatedServerList( 317 1234, 318 EpdgSelector.PROTO_FILTER_IPV4V6, 319 false /* isRoaming */, 320 isEmergency, 321 mMockNetwork, 322 new EpdgSelector.EpdgSelectorCallback() { 323 @Override 324 public void onServerListChanged( 325 int transactionId, ArrayList<InetAddress> validIPList) { 326 assertEquals(transactionId, 1234); 327 328 for (InetAddress mInetAddress : validIPList) { 329 testInetAddresses.add(mInetAddress); 330 } 331 Log.d(TAG, "onServerListChanged received"); 332 latch.countDown(); 333 } 334 335 @Override 336 public void onError(int transactionId, IwlanError epdgSelectorError) { 337 Log.d(TAG, "onError received"); 338 latch.countDown(); 339 } 340 }); 341 342 assertEquals(ret.getErrorType(), IwlanError.NO_ERROR); 343 latch.await(1, TimeUnit.SECONDS); 344 return testInetAddresses; 345 } 346 347 @Test testSetPcoData()348 public void testSetPcoData() throws Exception { 349 addTestPcoIdsToTestConfigBundle(); 350 351 boolean retIPv6 = mEpdgSelector.setPcoData(testPcoIdIPv6, pcoData); 352 boolean retIPv4 = mEpdgSelector.setPcoData(testPcoIdIPv4, pcoData); 353 boolean retIncorrect = mEpdgSelector.setPcoData(0xFF00, pcoData); 354 355 assertTrue(retIPv6); 356 assertTrue(retIPv4); 357 assertFalse(retIncorrect); 358 } 359 360 @Test testPcoResolutionMethod()361 public void testPcoResolutionMethod() throws Exception { 362 mTestBundle.putIntArray( 363 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 364 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_PCO}); 365 addTestPcoIdsToTestConfigBundle(); 366 367 mEpdgSelector.clearPcoData(); 368 boolean retIPv6 = 369 mEpdgSelector.setPcoData( 370 testPcoIdIPv6, InetAddress.getByName(TEST_IPV6_ADDRESS).getAddress()); 371 boolean retIPv4 = 372 mEpdgSelector.setPcoData( 373 testPcoIdIPv4, InetAddress.getByName(TEST_IP_ADDRESS).getAddress()); 374 375 ArrayList<InetAddress> testInetAddresses = 376 getValidatedServerListWithDefaultParams(false /* isEmergency */); 377 378 assertEquals(testInetAddresses.size(), 2); 379 assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IP_ADDRESS))); 380 assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IPV6_ADDRESS))); 381 } 382 addTestPcoIdsToTestConfigBundle()383 private void addTestPcoIdsToTestConfigBundle() { 384 mTestBundle.putInt(CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV6_INT, testPcoIdIPv6); 385 mTestBundle.putInt(CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV4_INT, testPcoIdIPv4); 386 } 387 388 @Test testCellularResolutionMethod()389 public void testCellularResolutionMethod() throws Exception { 390 testCellularResolutionMethod(false); 391 } 392 393 @Test testCellularResolutionMethodForEmergency()394 public void testCellularResolutionMethodForEmergency() throws Exception { 395 testCellularResolutionMethod(true); 396 } 397 testCellularResolutionMethod(boolean isEmergency)398 private void testCellularResolutionMethod(boolean isEmergency) throws Exception { 399 int testMcc = 311; 400 int testMnc = 120; 401 String testMccString = "311"; 402 String testMncString = "120"; 403 int testLac = 65484; 404 int testTac = 65484; 405 int testNrTac = 16764074; 406 407 List<CellInfo> fakeCellInfoArray = new ArrayList<CellInfo>(); 408 409 mTestBundle.putIntArray( 410 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 411 new int[] {CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC}); 412 413 // Set cell info mock 414 fakeCellInfoArray.add(mMockCellInfoGsm); 415 when(mMockCellInfoGsm.isRegistered()).thenReturn(true); 416 when(mMockCellInfoGsm.getCellIdentity()).thenReturn(mMockCellIdentityGsm); 417 when(mMockCellIdentityGsm.getMcc()).thenReturn(testMcc); 418 when(mMockCellIdentityGsm.getMnc()).thenReturn(testMnc); 419 when(mMockCellIdentityGsm.getLac()).thenReturn(testLac); 420 421 fakeCellInfoArray.add(mMockCellInfoWcdma); 422 when(mMockCellInfoWcdma.isRegistered()).thenReturn(true); 423 when(mMockCellInfoWcdma.getCellIdentity()).thenReturn(mMockCellIdentityWcdma); 424 when(mMockCellIdentityWcdma.getMcc()).thenReturn(testMcc); 425 when(mMockCellIdentityWcdma.getMnc()).thenReturn(testMnc); 426 when(mMockCellIdentityWcdma.getLac()).thenReturn(testLac); 427 428 fakeCellInfoArray.add(mMockCellInfoLte); 429 when(mMockCellInfoLte.isRegistered()).thenReturn(true); 430 when(mMockCellInfoLte.getCellIdentity()).thenReturn(mMockCellIdentityLte); 431 when(mMockCellIdentityLte.getMcc()).thenReturn(testMcc); 432 when(mMockCellIdentityLte.getMnc()).thenReturn(testMnc); 433 when(mMockCellIdentityLte.getTac()).thenReturn(testTac); 434 435 fakeCellInfoArray.add(mMockCellInfoNr); 436 when(mMockCellInfoNr.isRegistered()).thenReturn(true); 437 when(mMockCellInfoNr.getCellIdentity()).thenReturn(mMockCellIdentityNr); 438 when(mMockCellIdentityNr.getMccString()).thenReturn(testMccString); 439 when(mMockCellIdentityNr.getMncString()).thenReturn(testMncString); 440 when(mMockCellIdentityNr.getTac()).thenReturn(testNrTac); 441 442 when(mMockTelephonyManager.getAllCellInfo()).thenReturn(fakeCellInfoArray); 443 444 setAnswerForCellularMethod(isEmergency, 311, 120); 445 setAnswerForCellularMethod(isEmergency, 300, 120); 446 447 ArrayList<InetAddress> testInetAddresses = 448 getValidatedServerListWithDefaultParams(isEmergency); 449 450 assertEquals(testInetAddresses.size(), 3); 451 assertEquals(testInetAddresses.get(0), InetAddress.getByName(TEST_IP_ADDRESS)); 452 assertEquals(testInetAddresses.get(1), InetAddress.getByName(TEST_IP_ADDRESS_1)); 453 assertEquals(testInetAddresses.get(2), InetAddress.getByName(TEST_IP_ADDRESS_2)); 454 } 455 setAnswerForCellularMethod(boolean isEmergency, int mcc, int mnc)456 private void setAnswerForCellularMethod(boolean isEmergency, int mcc, int mnc) 457 throws Exception { 458 String expectedFqdn1 = 459 (isEmergency) 460 ? "lacffcc.sos.epdg.epc.mnc" + mnc + ".mcc" + mcc + ".pub.3gppnetwork.org" 461 : "lacffcc.epdg.epc.mnc" + mnc + ".mcc" + mcc + ".pub.3gppnetwork.org"; 462 String expectedFqdn2 = 463 (isEmergency) 464 ? "tac-lbcc.tac-hbff.tac.sos.epdg.epc.mnc" 465 + mnc 466 + ".mcc" 467 + mcc 468 + ".pub.3gppnetwork.org" 469 : "tac-lbcc.tac-hbff.tac.epdg.epc.mnc" 470 + mnc 471 + ".mcc" 472 + mcc 473 + ".pub.3gppnetwork.org"; 474 String expectedFqdn3 = 475 (isEmergency) 476 ? "tac-lbaa.tac-mbcc.tac-hbff.5gstac.sos.epdg.epc.mnc" 477 + mnc 478 + ".mcc" 479 + mcc 480 + ".pub.3gppnetwork.org" 481 : "tac-lbaa.tac-mbcc.tac-hbff.5gstac.epdg.epc.mnc" 482 + mnc 483 + ".mcc" 484 + mcc 485 + ".pub.3gppnetwork.org"; 486 487 mFakeDns.setAnswer(expectedFqdn1, new String[] {TEST_IP_ADDRESS}, TYPE_A); 488 mFakeDns.setAnswer(expectedFqdn2, new String[] {TEST_IP_ADDRESS_1}, TYPE_A); 489 mFakeDns.setAnswer(expectedFqdn3, new String[] {TEST_IP_ADDRESS_2}, TYPE_A); 490 } 491 492 /** 493 * Fakes DNS responses. 494 * 495 * <p>Allows test methods to configure the IP addresses that will be resolved by 496 * Network#getAllByName and by DnsResolver#query. 497 */ 498 class FakeDns { 499 /** Data class to record the Dns entry. */ 500 class DnsEntry { 501 final String mHostname; 502 final int mType; 503 final List<InetAddress> mAddresses; 504 DnsEntry(String host, int type, List<InetAddress> addr)505 DnsEntry(String host, int type, List<InetAddress> addr) { 506 mHostname = host; 507 mType = type; 508 mAddresses = addr; 509 } 510 // Full match or partial match that target host contains the entry hostname to support 511 // random private dns probe hostname. matches(String hostname, int type)512 private boolean matches(String hostname, int type) { 513 return hostname.equals(mHostname) && type == mType; 514 } 515 } 516 517 private final ArrayList<DnsEntry> mAnswers = new ArrayList<DnsEntry>(); 518 519 /** Clears all DNS entries. */ clearAll()520 private synchronized void clearAll() { 521 mAnswers.clear(); 522 } 523 524 /** Returns the answer for a given name and type on the given mock network. */ getAnswer(Object mock, String hostname, int type)525 private synchronized List<InetAddress> getAnswer(Object mock, String hostname, int type) { 526 return mAnswers.stream() 527 .filter(e -> e.matches(hostname, type)) 528 .map(answer -> answer.mAddresses) 529 .findFirst() 530 .orElse(null); 531 } 532 533 /** Sets the answer for a given name and type. */ setAnswer(String hostname, String[] answer, int type)534 private synchronized void setAnswer(String hostname, String[] answer, int type) 535 throws UnknownHostException { 536 DnsEntry record = new DnsEntry(hostname, type, generateAnswer(answer)); 537 // Remove the existing one. 538 mAnswers.removeIf(entry -> entry.matches(hostname, type)); 539 // Add or replace a new record. 540 mAnswers.add(record); 541 } 542 generateAnswer(String[] answer)543 private List<InetAddress> generateAnswer(String[] answer) { 544 if (answer == null) return new ArrayList<>(); 545 return Arrays.stream(answer) 546 .map(addr -> InetAddresses.parseNumericAddress(addr)) 547 .collect(toList()); 548 } 549 550 // Regardless of the type, depends on what the responses contained in the network. queryAllTypes(Object mock, String hostname)551 private List<InetAddress> queryAllTypes(Object mock, String hostname) { 552 List<InetAddress> answer = new ArrayList<>(); 553 addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_A)); 554 addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_AAAA)); 555 return answer; 556 } 557 addAllIfNotNull(List<InetAddress> list, List<InetAddress> c)558 private void addAllIfNotNull(List<InetAddress> list, List<InetAddress> c) { 559 if (c != null) { 560 list.addAll(c); 561 } 562 } 563 564 /** Starts mocking DNS queries. */ startMocking()565 private void startMocking() throws UnknownHostException { 566 doAnswer( 567 invocation -> { 568 return mockQuery( 569 invocation, 570 1 /* posHostname */, 571 3 /* posExecutor */, 572 5 /* posCallback */, 573 -1 /* posType */); 574 }) 575 .when(mMockDnsResolver) 576 .query(any(), any(), anyInt(), any(), any(), any()); 577 } 578 579 // Mocking queries on DnsResolver#query. mockQuery( InvocationOnMock invocation, int posHostname, int posExecutor, int posCallback, int posType)580 private Answer mockQuery( 581 InvocationOnMock invocation, 582 int posHostname, 583 int posExecutor, 584 int posCallback, 585 int posType) { 586 String hostname = (String) invocation.getArgument(posHostname); 587 Executor executor = (Executor) invocation.getArgument(posExecutor); 588 DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(posCallback); 589 List<InetAddress> answer; 590 591 answer = queryAllTypes(invocation.getMock(), hostname); 592 593 if (answer != null && answer.size() > 0) { 594 new Handler(Looper.getMainLooper()) 595 .post( 596 () -> { 597 executor.execute(() -> callback.onAnswer(answer, 0)); 598 }); 599 } 600 // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE. 601 return null; 602 } 603 } 604 } 605