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 android.content.Context; 20 import android.net.Network; 21 import android.support.annotation.IntDef; 22 import android.support.annotation.NonNull; 23 import android.telephony.CarrierConfigManager; 24 import android.telephony.CellIdentityGsm; 25 import android.telephony.CellIdentityLte; 26 import android.telephony.CellIdentityNr; 27 import android.telephony.CellIdentityWcdma; 28 import android.telephony.CellInfo; 29 import android.telephony.CellInfoGsm; 30 import android.telephony.CellInfoLte; 31 import android.telephony.CellInfoNr; 32 import android.telephony.CellInfoWcdma; 33 import android.telephony.SubscriptionInfo; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.TelephonyManager; 36 import android.util.Log; 37 38 import com.android.internal.annotations.VisibleForTesting; 39 40 import com.google.android.iwlan.IwlanError; 41 import com.google.android.iwlan.IwlanHelper; 42 43 import java.net.Inet4Address; 44 import java.net.Inet6Address; 45 import java.net.InetAddress; 46 import java.util.*; 47 import java.util.concurrent.ConcurrentHashMap; 48 49 public class EpdgSelector { 50 private static final String TAG = "EpdgSelector"; 51 private Context mContext; 52 private int mSlotId; 53 private static ConcurrentHashMap<Integer, EpdgSelector> mSelectorInstances = 54 new ConcurrentHashMap<>(); 55 private int mV4PcoId = -1; 56 private int mV6PcoId = -1; 57 private byte[] mV4PcoData = null; 58 private byte[] mV6PcoData = null; 59 60 final Comparator<InetAddress> inetAddressComparator = 61 new Comparator<InetAddress>() { 62 @Override 63 public int compare(InetAddress ip1, InetAddress ip2) { 64 if ((ip1 instanceof Inet4Address) && (ip2 instanceof Inet6Address)) { 65 return -1; 66 } else if ((ip1 instanceof Inet6Address) && (ip2 instanceof Inet4Address)) { 67 return 1; 68 } else { 69 return 0; 70 } 71 } 72 }; 73 74 public static final int PROTO_FILTER_IPV4 = 0; 75 public static final int PROTO_FILTER_IPV6 = 1; 76 public static final int PROTO_FILTER_IPV4V6 = 2; 77 78 @IntDef({PROTO_FILTER_IPV4, PROTO_FILTER_IPV6, PROTO_FILTER_IPV4V6}) 79 @interface ProtoFilter {} 80 81 public interface EpdgSelectorCallback { 82 /*gives priority ordered list of addresses*/ onServerListChanged(int transactionId, ArrayList<InetAddress> validIPList)83 void onServerListChanged(int transactionId, ArrayList<InetAddress> validIPList); 84 onError(int transactionId, IwlanError error)85 void onError(int transactionId, IwlanError error); 86 } 87 88 @VisibleForTesting EpdgSelector(Context context, int slotId)89 EpdgSelector(Context context, int slotId) { 90 mContext = context; 91 mSlotId = slotId; 92 } 93 getSelectorInstance(Context context, int slotId)94 public static EpdgSelector getSelectorInstance(Context context, int slotId) { 95 mSelectorInstances.computeIfAbsent(slotId, k -> new EpdgSelector(context, slotId)); 96 return mSelectorInstances.get(slotId); 97 } 98 setPcoData(int pcoId, byte[] pcoData)99 public boolean setPcoData(int pcoId, byte[] pcoData) { 100 Log.d(TAG, "onReceive PcoId:" + String.format("0x%04x", pcoId) + " PcoData:" + pcoData); 101 102 int PCO_ID_IPV6 = 103 IwlanHelper.getConfig( 104 CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV6_INT, mContext, mSlotId); 105 int PCO_ID_IPV4 = 106 IwlanHelper.getConfig( 107 CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV4_INT, mContext, mSlotId); 108 109 Log.d( 110 TAG, 111 "PCO_ID_IPV6:" 112 + String.format("0x%04x", PCO_ID_IPV6) 113 + " PCO_ID_IPV4:" 114 + String.format("0x%04x", PCO_ID_IPV4)); 115 116 if (pcoId == PCO_ID_IPV4) { 117 mV4PcoId = pcoId; 118 mV4PcoData = pcoData; 119 return true; 120 } else if (pcoId == PCO_ID_IPV6) { 121 mV6PcoId = pcoId; 122 mV6PcoData = pcoData; 123 return true; 124 } 125 126 return false; 127 } 128 clearPcoData()129 public void clearPcoData() { 130 Log.d(TAG, "Clear PCO data"); 131 mV4PcoId = -1; 132 mV6PcoId = -1; 133 mV4PcoData = null; 134 mV6PcoData = null; 135 } 136 getIP( String domainName, int filter, ArrayList<InetAddress> validIpList, Network network)137 private void getIP( 138 String domainName, int filter, ArrayList<InetAddress> validIpList, Network network) { 139 InetAddress[] ipList; 140 141 // Get All IP for each domain name 142 Log.d(TAG, "Input domainName : " + domainName); 143 try { 144 ipList = network.getAllByName(domainName); 145 } catch (Exception e) { 146 Log.e(TAG, "Exception when querying IP address : " + e); 147 return; 148 } 149 150 if (ipList == null) { 151 Log.e(TAG, "Get empty IP address list"); 152 return; 153 } 154 155 // Filter the IP list by input ProtoFilter 156 for (InetAddress ipAddress : ipList) { 157 switch (filter) { 158 case PROTO_FILTER_IPV4: 159 if (ipAddress instanceof Inet4Address) { 160 validIpList.add(ipAddress); 161 } 162 break; 163 case PROTO_FILTER_IPV6: 164 if (ipAddress instanceof Inet6Address) { 165 validIpList.add(ipAddress); 166 } 167 break; 168 case PROTO_FILTER_IPV4V6: 169 validIpList.add(ipAddress); 170 break; 171 default: 172 Log.d(TAG, "Invalid ProtoFilter : " + filter); 173 } 174 } 175 } 176 getPlmnList()177 private String[] getPlmnList() { 178 List<String> plmnsFromSubInfo = new ArrayList<>(); 179 180 List<String> plmnsFromCarrierConfig = 181 new ArrayList<>( 182 Arrays.asList( 183 IwlanHelper.getConfig( 184 CarrierConfigManager.Iwlan.KEY_MCC_MNCS_STRING_ARRAY, 185 mContext, 186 mSlotId))); 187 Log.d(TAG, "plmnsFromCarrierConfig:" + plmnsFromCarrierConfig); 188 189 // Get Ehplmns & mccmnc from SubscriptionManager 190 SubscriptionManager subscriptionManager = 191 mContext.getSystemService(SubscriptionManager.class); 192 if (subscriptionManager == null) { 193 Log.e(TAG, "SubscriptionManager is NULL"); 194 return plmnsFromCarrierConfig.toArray(new String[plmnsFromCarrierConfig.size()]); 195 } 196 197 SubscriptionInfo subInfo = 198 subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(mSlotId); 199 if (subInfo == null) { 200 Log.e(TAG, "SubscriptionInfo is NULL"); 201 return plmnsFromCarrierConfig.toArray(new String[plmnsFromCarrierConfig.size()]); 202 } 203 204 // There are three sources of plmns - sim plmn, plmn list from carrier config and 205 // Ehplmn list from subscription info. 206 // The plmns are prioritized as follows: 207 // 1. Sim plmn 208 // 2. Plmns common to both lists. 209 // 3. Remaining plmns in the lists. 210 List<String> combinedList = new ArrayList<>(); 211 // Get MCCMNC from IMSI 212 String plmnFromImsi = 213 new StringBuilder() 214 .append(subInfo.getMccString()) 215 .append("-") 216 .append(subInfo.getMncString()) 217 .toString(); 218 combinedList.add(plmnFromImsi); 219 220 // Get Ehplmns from TelephonyManager 221 for (String ehplmn : getEhplmns()) { 222 if (ehplmn.length() == 5 || ehplmn.length() == 6) { 223 StringBuilder str = new StringBuilder(ehplmn); 224 str.insert(3, "-"); 225 plmnsFromSubInfo.add(str.toString()); 226 } 227 } 228 229 Log.d(TAG, "plmnsFromSubInfo:" + plmnsFromSubInfo); 230 231 // To avoid double adding plmn from imsi 232 plmnsFromCarrierConfig.removeIf(i -> i.equals(plmnFromImsi)); 233 plmnsFromSubInfo.removeIf(i -> i.equals(plmnFromImsi)); 234 235 for (Iterator<String> iterator = plmnsFromCarrierConfig.iterator(); iterator.hasNext(); ) { 236 String plmn = iterator.next(); 237 if (plmnsFromSubInfo.contains(plmn)) { 238 combinedList.add(plmn); 239 plmnsFromSubInfo.remove(plmn); 240 iterator.remove(); 241 } 242 } 243 244 combinedList.addAll(plmnsFromSubInfo); 245 combinedList.addAll(plmnsFromCarrierConfig); 246 247 Log.d(TAG, "Final plmn list:" + combinedList); 248 return combinedList.toArray(new String[combinedList.size()]); 249 } 250 removeDuplicateIp(ArrayList<InetAddress> validIpList)251 private ArrayList<InetAddress> removeDuplicateIp(ArrayList<InetAddress> validIpList) { 252 ArrayList<InetAddress> resultIpList = new ArrayList<InetAddress>(); 253 254 for (Iterator<InetAddress> iterator = validIpList.iterator(); iterator.hasNext(); ) { 255 InetAddress validIp = iterator.next(); 256 257 if (!resultIpList.contains(validIp)) { 258 resultIpList.add(validIp); 259 } 260 } 261 262 return resultIpList; 263 } 264 splitMccMnc(String plmn)265 private String[] splitMccMnc(String plmn) { 266 String[] mccmnc = plmn.split("-"); 267 mccmnc[1] = String.format("%03d", Integer.parseInt(mccmnc[1])); 268 return mccmnc; 269 } 270 getEhplmns()271 private List<String> getEhplmns() { 272 TelephonyManager mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 273 mTelephonyManager = 274 mTelephonyManager.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId)); 275 276 if (mTelephonyManager == null) { 277 Log.e(TAG, "TelephonyManager is NULL"); 278 return new ArrayList<String>(); 279 } else { 280 return mTelephonyManager.getEquivalentHomePlmns(); 281 } 282 } 283 resolutionMethodStatic( int filter, ArrayList<InetAddress> validIpList, boolean isRoaming, Network network)284 private void resolutionMethodStatic( 285 int filter, ArrayList<InetAddress> validIpList, boolean isRoaming, Network network) { 286 String[] domainNames = null; 287 288 Log.d(TAG, "STATIC Method"); 289 290 // Get the static domain names from carrier config 291 // Config obtained in form of a list of domain names separated by 292 // a delimeter is only used for testing purpose. 293 // TODO: need to consider APM on/no cellular condition. 294 if (isRoaming && !inSameCountry()) { 295 domainNames = 296 getDomainNames( 297 CarrierConfigManager.Iwlan.KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING); 298 } 299 if (domainNames == null 300 && (domainNames = 301 getDomainNames( 302 CarrierConfigManager.Iwlan.KEY_EPDG_STATIC_ADDRESS_STRING)) 303 == null) { 304 Log.d(TAG, "Static address string is null"); 305 return; 306 } 307 308 Log.d(TAG, "Static Domain Names: " + Arrays.toString(domainNames)); 309 for (String domainName : domainNames) { 310 getIP(domainName, filter, validIpList, network); 311 } 312 } 313 getDomainNames(String key)314 private String[] getDomainNames(String key) { 315 String configValue = (String) IwlanHelper.getConfig(key, mContext, mSlotId); 316 if (configValue == null || configValue.isEmpty()) { 317 Log.d(TAG, key + " string is null"); 318 return null; 319 } 320 return configValue.split(","); 321 } 322 inSameCountry()323 private boolean inSameCountry() { 324 boolean inSameCountry = true; 325 326 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 327 tm = tm.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId)); 328 329 if (tm != null) { 330 String simCountry = tm.getSimCountryIso(); 331 String currentCountry = tm.getNetworkCountryIso(); 332 if (simCountry != null 333 && !simCountry.isEmpty() 334 && currentCountry != null 335 && !currentCountry.isEmpty()) { 336 Log.d(TAG, "simCountry = " + simCountry + ", currentCountry = " + currentCountry); 337 inSameCountry = simCountry.equalsIgnoreCase(currentCountry); 338 } 339 } 340 341 return inSameCountry; 342 } 343 resolutionMethodPlmn( int filter, ArrayList<InetAddress> validIpList, boolean isEmergency, Network network)344 private void resolutionMethodPlmn( 345 int filter, ArrayList<InetAddress> validIpList, boolean isEmergency, Network network) { 346 String[] plmnList; 347 StringBuilder domainName = new StringBuilder(); 348 349 Log.d(TAG, "PLMN Method"); 350 351 plmnList = getPlmnList(); 352 for (String plmn : plmnList) { 353 String[] mccmnc = splitMccMnc(plmn); 354 /* 355 * Operator Identifier based ePDG FQDN format: 356 * epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 357 * 358 * Operator Identifier based Emergency ePDG FQDN format: 359 * sos.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 360 */ 361 if (isEmergency) { 362 domainName.append("sos."); 363 } 364 365 domainName 366 .append("epdg.epc.mnc") 367 .append(mccmnc[1]) 368 .append(".mcc") 369 .append(mccmnc[0]) 370 .append(".pub.3gppnetwork.org"); 371 getIP(domainName.toString(), filter, validIpList, network); 372 domainName.setLength(0); 373 } 374 } 375 resolutionMethodCellularLoc( int filter, ArrayList<InetAddress> validIpList, boolean isEmergency, Network network)376 private void resolutionMethodCellularLoc( 377 int filter, ArrayList<InetAddress> validIpList, boolean isEmergency, Network network) { 378 String[] plmnList; 379 StringBuilder domainName = new StringBuilder(); 380 381 Log.d(TAG, "CELLULAR_LOC Method"); 382 383 TelephonyManager mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 384 mTelephonyManager = 385 mTelephonyManager.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId)); 386 387 if (mTelephonyManager == null) { 388 Log.e(TAG, "TelephonyManager is NULL"); 389 return; 390 } 391 392 List<CellInfo> cellInfoList = mTelephonyManager.getAllCellInfo(); 393 if (cellInfoList == null) { 394 Log.e(TAG, "cellInfoList is NULL"); 395 return; 396 } 397 398 for (CellInfo cellInfo : cellInfoList) { 399 if (!cellInfo.isRegistered()) { 400 continue; 401 } 402 403 if (cellInfo instanceof CellInfoGsm) { 404 CellIdentityGsm gsmCellId = ((CellInfoGsm) cellInfo).getCellIdentity(); 405 String lacString = String.format("%04x", gsmCellId.getLac()); 406 407 lacDomainNameResolution(filter, validIpList, lacString, isEmergency, network); 408 } else if (cellInfo instanceof CellInfoWcdma) { 409 CellIdentityWcdma wcdmaCellId = ((CellInfoWcdma) cellInfo).getCellIdentity(); 410 String lacString = String.format("%04x", wcdmaCellId.getLac()); 411 412 lacDomainNameResolution(filter, validIpList, lacString, isEmergency, network); 413 } else if (cellInfo instanceof CellInfoLte) { 414 CellIdentityLte lteCellId = ((CellInfoLte) cellInfo).getCellIdentity(); 415 String tacString = String.format("%04x", lteCellId.getTac()); 416 String[] tacSubString = new String[2]; 417 tacSubString[0] = tacString.substring(0, 2); 418 tacSubString[1] = tacString.substring(2); 419 420 plmnList = getPlmnList(); 421 for (String plmn : plmnList) { 422 String[] mccmnc = splitMccMnc(plmn); 423 /** 424 * Tracking Area Identity based ePDG FQDN format: 425 * tac-lb<TAC-low-byte>.tac-hb<TAC-high-byte>.tac. 426 * epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 427 * 428 * <p>Tracking Area Identity based Emergency ePDG FQDN format: 429 * tac-lb<TAC-low-byte>.tac-hb<TAC-highbyte>.tac. 430 * sos.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org" 431 */ 432 domainName 433 .append("tac-lb") 434 .append(tacSubString[1]) 435 .append(".tac-hb") 436 .append(tacSubString[0]); 437 if (isEmergency) { 438 domainName.append(".tac.sos.epdg.epc.mnc"); 439 } else { 440 domainName.append(".tac.epdg.epc.mnc"); 441 } 442 domainName 443 .append(mccmnc[1]) 444 .append(".mcc") 445 .append(mccmnc[0]) 446 .append(".pub.3gppnetwork.org"); 447 getIP(domainName.toString(), filter, validIpList, network); 448 domainName.setLength(0); 449 } 450 } else if (cellInfo instanceof CellInfoNr) { 451 CellIdentityNr nrCellId = 452 (CellIdentityNr) ((CellInfoNr) cellInfo).getCellIdentity(); 453 String tacString = String.format("%06x", nrCellId.getTac()); 454 String[] tacSubString = new String[3]; 455 tacSubString[0] = tacString.substring(0, 2); 456 tacSubString[1] = tacString.substring(2, 4); 457 tacSubString[2] = tacString.substring(4); 458 459 plmnList = getPlmnList(); 460 for (String plmn : plmnList) { 461 String[] mccmnc = splitMccMnc(plmn); 462 /** 463 * 5GS Tracking Area Identity based ePDG FQDN format: 464 * tac-lb<TAC-low-byte>.tac-mb<TAC-middle-byte>.tac-hb<TAC-high-byte>. 465 * 5gstac.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 466 * 467 * <p>5GS Tracking Area Identity based Emergency ePDG FQDN format: 468 * tac-lb<TAC-low-byte>.tac-mb<TAC-middle-byte>.tac-hb<TAC-high-byte>. 469 * 5gstac.sos.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 470 */ 471 domainName 472 .append("tac-lb") 473 .append(tacSubString[2]) 474 .append(".tac-mb") 475 .append(tacSubString[1]) 476 .append(".tac-hb") 477 .append(tacSubString[0]); 478 if (isEmergency) { 479 domainName.append(".5gstac.sos.epdg.epc.mnc"); 480 } else { 481 domainName.append(".5gstac.epdg.epc.mnc"); 482 } 483 domainName 484 .append(mccmnc[1]) 485 .append(".mcc") 486 .append(mccmnc[0]) 487 .append(".pub.3gppnetwork.org"); 488 getIP(domainName.toString(), filter, validIpList, network); 489 domainName.setLength(0); 490 } 491 } else { 492 Log.d(TAG, "This cell doesn't contain LAC/TAC info"); 493 } 494 } 495 } 496 lacDomainNameResolution( int filter, ArrayList<InetAddress> validIpList, String lacString, boolean isEmergency, Network network)497 private void lacDomainNameResolution( 498 int filter, 499 ArrayList<InetAddress> validIpList, 500 String lacString, 501 boolean isEmergency, 502 Network network) { 503 String[] plmnList; 504 StringBuilder domainName = new StringBuilder(); 505 506 plmnList = getPlmnList(); 507 for (String plmn : plmnList) { 508 String[] mccmnc = splitMccMnc(plmn); 509 /** 510 * Location Area Identity based ePDG FQDN format: 511 * lac<LAC>.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 512 * 513 * <p>Location Area Identity based Emergency ePDG FQDN format: 514 * lac<LAC>.sos.epdg.epc.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org 515 */ 516 domainName.append("lac").append(lacString); 517 if (isEmergency) { 518 domainName.append(".sos.epdg.epc.mnc"); 519 } else { 520 domainName.append(".epdg.epc.mnc"); 521 } 522 domainName 523 .append(mccmnc[1]) 524 .append(".mcc") 525 .append(mccmnc[0]) 526 .append(".pub.3gppnetwork.org"); 527 528 getIP(domainName.toString(), filter, validIpList, network); 529 domainName.setLength(0); 530 } 531 } 532 resolutionMethodPco(int filter, ArrayList<InetAddress> validIpList)533 private void resolutionMethodPco(int filter, ArrayList<InetAddress> validIpList) { 534 Log.d(TAG, "PCO Method"); 535 536 int PCO_ID_IPV6 = 537 IwlanHelper.getConfig( 538 CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV6_INT, mContext, mSlotId); 539 int PCO_ID_IPV4 = 540 IwlanHelper.getConfig( 541 CarrierConfigManager.Iwlan.KEY_EPDG_PCO_ID_IPV4_INT, mContext, mSlotId); 542 543 switch (filter) { 544 case PROTO_FILTER_IPV4: 545 if (mV4PcoId != PCO_ID_IPV4) { 546 clearPcoData(); 547 } else { 548 getInetAddressWithPcoData(mV4PcoData, validIpList); 549 } 550 break; 551 case PROTO_FILTER_IPV6: 552 if (mV6PcoId != PCO_ID_IPV6) { 553 clearPcoData(); 554 } else { 555 getInetAddressWithPcoData(mV6PcoData, validIpList); 556 } 557 break; 558 case PROTO_FILTER_IPV4V6: 559 if ((mV4PcoId != PCO_ID_IPV4) || (mV6PcoId != PCO_ID_IPV6)) { 560 clearPcoData(); 561 } else { 562 getInetAddressWithPcoData(mV4PcoData, validIpList); 563 getInetAddressWithPcoData(mV6PcoData, validIpList); 564 } 565 break; 566 default: 567 Log.d(TAG, "Invalid ProtoFilter : " + filter); 568 } 569 } 570 getInetAddressWithPcoData(byte[] pcoData, ArrayList<InetAddress> validIpList)571 private void getInetAddressWithPcoData(byte[] pcoData, ArrayList<InetAddress> validIpList) { 572 InetAddress ipAddress; 573 if (pcoData != null && pcoData.length > 0) { 574 try { 575 ipAddress = InetAddress.getByAddress(pcoData); 576 validIpList.add(ipAddress); 577 } catch (Exception e) { 578 Log.e(TAG, "Exception when querying IP address : " + e); 579 } 580 } else { 581 Log.d(TAG, "Empty PCO data"); 582 } 583 } 584 getValidatedServerList( int transactionId, @ProtoFilter int filter, boolean isRoaming, boolean isEmergency, @NonNull Network network, EpdgSelectorCallback selectorCallback)585 public IwlanError getValidatedServerList( 586 int transactionId, 587 @ProtoFilter int filter, 588 boolean isRoaming, 589 boolean isEmergency, 590 @NonNull Network network, 591 EpdgSelectorCallback selectorCallback) { 592 ArrayList<InetAddress> validIpList = new ArrayList<InetAddress>(); 593 StringBuilder domainName = new StringBuilder(); 594 595 Runnable doValidation = 596 () -> { 597 Log.d(TAG, "Processing request with transactionId: " + transactionId); 598 String[] plmnList; 599 600 int[] addrResolutionMethods = 601 IwlanHelper.getConfig( 602 CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, 603 mContext, 604 mSlotId); 605 606 for (int addrResolutionMethod : addrResolutionMethods) { 607 switch (addrResolutionMethod) { 608 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_STATIC: 609 resolutionMethodStatic(filter, validIpList, isRoaming, network); 610 break; 611 612 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_PLMN: 613 resolutionMethodPlmn(filter, validIpList, isEmergency, network); 614 break; 615 616 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_PCO: 617 resolutionMethodPco(filter, validIpList); 618 break; 619 620 case CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC: 621 resolutionMethodCellularLoc( 622 filter, validIpList, isEmergency, network); 623 break; 624 625 default: 626 Log.d( 627 TAG, 628 "Incorrect address resolution method " 629 + addrResolutionMethod); 630 } 631 } 632 633 if (selectorCallback != null) { 634 if (!validIpList.isEmpty()) { 635 Collections.sort(validIpList, inetAddressComparator); 636 selectorCallback.onServerListChanged( 637 transactionId, removeDuplicateIp(validIpList)); 638 } else { 639 selectorCallback.onError( 640 transactionId, 641 new IwlanError( 642 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED)); 643 } 644 } 645 }; 646 Thread subThread = new Thread(doValidation); 647 subThread.start(); 648 return new IwlanError(IwlanError.NO_ERROR); 649 } 650 } 651