1 /* 2 * Copyright (C) 2021 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.telephony.qns; 18 19 import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED; 20 import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED; 21 22 import static com.android.telephony.qns.wfc.WfcCarrierConfigManager.CONFIG_DEFAULT_VOWIFI_REGISTATION_TIMER; 23 import static com.android.telephony.qns.wfc.WfcCarrierConfigManager.KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.Context; 28 import android.net.NetworkCapabilities; 29 import android.os.Handler; 30 import android.os.PersistableBundle; 31 import android.os.SystemClock; 32 import android.telephony.AccessNetworkConstants; 33 import android.telephony.Annotation.NetCapability; 34 import android.telephony.CarrierConfigManager; 35 import android.telephony.ServiceState; 36 import android.telephony.SubscriptionInfo; 37 import android.telephony.SubscriptionManager; 38 import android.telephony.TelephonyManager; 39 import android.telephony.data.ApnSetting; 40 import android.text.TextUtils; 41 import android.util.Log; 42 43 import java.io.BufferedReader; 44 import java.io.ByteArrayInputStream; 45 import java.io.InputStream; 46 import java.io.InputStreamReader; 47 import java.util.ArrayList; 48 import java.util.Arrays; 49 import java.util.Collection; 50 import java.util.Collections; 51 import java.util.List; 52 import java.util.Locale; 53 import java.util.Set; 54 import java.util.concurrent.Executor; 55 import java.util.concurrent.RejectedExecutionException; 56 import java.util.stream.Collectors; 57 import java.util.stream.Stream; 58 59 /** This class contains QualifiedNetworksService specific utility functions */ 60 class QnsUtils { 61 62 private static final String CARRIER_ID_PREFIX = "carrier_config_carrierid_"; 63 64 /** 65 * Get supported APN types 66 * 67 * @param apnTypeBitmask bitmask of APN types. 68 * @return list of APN types 69 */ 70 @ApnSetting.ApnType getApnTypes(int apnTypeBitmask)71 static List<Integer> getApnTypes(int apnTypeBitmask) { 72 List<Integer> types = new ArrayList<>(); 73 74 if ((apnTypeBitmask & ApnSetting.TYPE_DEFAULT) == ApnSetting.TYPE_DEFAULT) { 75 types.add(ApnSetting.TYPE_DEFAULT); 76 apnTypeBitmask &= ~ApnSetting.TYPE_DEFAULT; 77 } 78 while (apnTypeBitmask != 0) { 79 int highestApnTypeBit = Integer.highestOneBit(apnTypeBitmask); 80 types.add(highestApnTypeBit); 81 apnTypeBitmask &= ~highestApnTypeBit; 82 } 83 return types; 84 } 85 86 /** 87 * Get names of AccessNetworkTypes 88 * 89 * @param accessNetworkTypes list of accessNetworkType 90 * @return String of AccessNetworkTypes name 91 */ getStringAccessNetworkTypes(List<Integer> accessNetworkTypes)92 static String getStringAccessNetworkTypes(List<Integer> accessNetworkTypes) { 93 if (accessNetworkTypes == null || accessNetworkTypes.size() == 0) { 94 return "[empty]"; 95 } 96 List<String> types = new ArrayList<>(); 97 for (Integer net : accessNetworkTypes) { 98 types.add(QnsConstants.accessNetworkTypeToString(net)); 99 } 100 return TextUtils.join("|", types); 101 } 102 103 /** 104 * Get a subId per slot id. 105 * 106 * @param context Context 107 * @param slotId slot id. 108 * @return Subscription id per slot id. 109 */ getSubId(Context context, int slotId)110 static int getSubId(Context context, int slotId) { 111 try { 112 return getSubscriptionInfo(context, slotId).getSubscriptionId(); 113 } catch (IllegalStateException e) { 114 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 115 } 116 } 117 118 /** 119 * This method validates the slot index. 120 * 121 * @param context Context 122 * @param slotIndex slot index 123 * @return returns true if slotIndex is valid; otherwise false. 124 */ isValidSlotIndex(Context context, int slotIndex)125 static boolean isValidSlotIndex(Context context, int slotIndex) { 126 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 127 return slotIndex >= 0 && tm != null && slotIndex < tm.getActiveModemCount(); 128 } 129 isDefaultDataSubs(int slotId)130 static boolean isDefaultDataSubs(int slotId) { 131 int ddsSlotId = 132 SubscriptionManager.getSlotIndex( 133 SubscriptionManager.getDefaultDataSubscriptionId()); 134 if (ddsSlotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 135 return ddsSlotId == slotId; 136 } 137 return false; 138 } 139 getSystemElapsedRealTime()140 static long getSystemElapsedRealTime() { 141 return SystemClock.elapsedRealtime(); 142 } 143 getSubscriptionInfo(Context context, int slotId)144 private static SubscriptionInfo getSubscriptionInfo(Context context, int slotId) 145 throws IllegalStateException { 146 SubscriptionManager sm = context.getSystemService(SubscriptionManager.class); 147 SubscriptionInfo info = sm.getActiveSubscriptionInfoForSimSlotIndex(slotId); 148 149 if (info == null) { 150 throw new IllegalStateException("Subscription info is null."); 151 } 152 153 return info; 154 } 155 156 /** isCrossSimCallingEnabled */ isCrossSimCallingEnabled(QnsImsManager imsManager)157 public static boolean isCrossSimCallingEnabled(QnsImsManager imsManager) { 158 try { 159 return imsManager.isCrossSimCallingEnabled(); 160 } catch (Exception e) { 161 // Fail to query Cross-SIM calling setting, just return false to avoid an exception. 162 } 163 return false; 164 } 165 166 /** isWfcEnabled */ isWfcEnabled( QnsImsManager imsManager, QnsProvisioningListener listener, boolean roaming)167 public static boolean isWfcEnabled( 168 QnsImsManager imsManager, QnsProvisioningListener listener, boolean roaming) { 169 try { 170 boolean bWfcEnabledByUser; 171 boolean bWfcEnabledByPlatform = imsManager.isWfcEnabledByPlatform(); 172 boolean bWfcProvisionedOnDevice = imsManager.isWfcProvisionedOnDevice(); 173 if (roaming) { 174 bWfcEnabledByUser = imsManager.isWfcRoamingEnabledByUser(); 175 try { 176 boolean bWfcRoamingEnabled = 177 listener.getLastProvisioningWfcRoamingEnabledInfo(); 178 bWfcEnabledByUser = bWfcEnabledByUser && (bWfcRoamingEnabled); 179 } catch (Exception e) { 180 log("got exception e:" + e); 181 } 182 } else { 183 bWfcEnabledByUser = imsManager.isWfcEnabledByUser(); 184 } 185 log( 186 "isWfcEnabled slot:" 187 + imsManager.getSlotIndex() 188 + " byUser:" 189 + bWfcEnabledByUser 190 + " byPlatform:" 191 + bWfcEnabledByPlatform 192 + " ProvisionedOnDevice:" 193 + bWfcProvisionedOnDevice 194 + " roam:" 195 + roaming); 196 return bWfcEnabledByUser && bWfcEnabledByPlatform && bWfcProvisionedOnDevice; 197 } catch (Exception e) { 198 loge("isWfcEnabled exception:" + e); 199 // Fail to query, just return false to avoid an exception. 200 } 201 return false; 202 } 203 204 /** isWfcEnabledByPlatform */ isWfcEnabledByPlatform(QnsImsManager imsManager)205 public static boolean isWfcEnabledByPlatform(QnsImsManager imsManager) { 206 try { 207 boolean bWfcEnabledByPlatform = imsManager.isWfcEnabledByPlatform(); 208 log( 209 "isWfcEnabledByPlatform:" 210 + bWfcEnabledByPlatform 211 + " slot:" 212 + imsManager.getSlotIndex()); 213 return bWfcEnabledByPlatform; 214 } catch (Exception e) { 215 loge("isWfcEnabledByPlatform exception:" + e); 216 // Fail to query, just return false to avoid an exception. 217 } 218 return false; 219 } 220 221 /** getWfcMode */ getWfcMode(QnsImsManager imsManager, boolean roaming)222 public static int getWfcMode(QnsImsManager imsManager, boolean roaming) { 223 try { 224 int wfcMode = imsManager.getWfcMode(roaming); 225 log( 226 "getWfcMode slot:" 227 + imsManager.getSlotIndex() 228 + " wfcMode:" 229 + wfcMode 230 + " roaming:" 231 + roaming); 232 return wfcMode; 233 } catch (Exception e) { 234 // Fail to query, just return false to avoid an exception. 235 } 236 return roaming ? WIFI_MODE_WIFI_PREFERRED : WIFI_MODE_CELLULAR_PREFERRED; 237 } 238 239 /** 240 * This method provides the access network type for the given data registration state and 241 * Network Type. It will return value as UNKNOWN(0) if registration state is not in service. 242 * 243 * @param dataRegState Data registration state. 244 * @param dataNetworkType Data network type 245 * @return int value of the AccessNetworkType mapped to NetworkType. And UNKNOWN(0) if 246 * registration state is not in service. 247 */ getCellularAccessNetworkType(int dataRegState, int dataNetworkType)248 static int getCellularAccessNetworkType(int dataRegState, int dataNetworkType) { 249 if (dataRegState == ServiceState.STATE_IN_SERVICE) { 250 return QnsConstants.networkTypeToAccessNetworkType(dataNetworkType); 251 } 252 return AccessNetworkConstants.AccessNetworkType.UNKNOWN; 253 } 254 isWifiCallingAvailable(Context context, int slotId)255 static boolean isWifiCallingAvailable(Context context, int slotId) { 256 try { 257 int subId = QnsUtils.getSubId(context, slotId); 258 TelephonyManager telephonyManager = 259 context.getSystemService(TelephonyManager.class).createForSubscriptionId(subId); 260 return telephonyManager.isWifiCallingAvailable(); 261 } catch (Exception e) { 262 loge("isWifiCallingAvailable has exception : " + e); 263 } 264 return false; 265 } 266 267 @AccessNetworkConstants.TransportType getTransportTypeFromAccessNetwork( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork)268 static int getTransportTypeFromAccessNetwork( 269 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork) { 270 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN) { 271 return AccessNetworkConstants.TRANSPORT_TYPE_WLAN; 272 } else if (accessNetwork != AccessNetworkConstants.AccessNetworkType.UNKNOWN) { 273 return AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 274 } 275 return AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 276 } 277 278 /** 279 * Get Set of network capabilities from string joined by {@code |}, space is ignored. If input 280 * string contains unknown capability or malformatted(e.g. empty string), -1 is included in the 281 * returned set. 282 * 283 * @param capabilitiesString capability strings joined by {@code |} 284 * @return Set of capabilities 285 */ 286 @NetCapability getNetworkCapabilitiesFromString(@onNull String capabilitiesString)287 static Set<Integer> getNetworkCapabilitiesFromString(@NonNull String capabilitiesString) { 288 // e.g. "IMS|" is not allowed 289 if (!capabilitiesString.matches("(\\s*[a-zA-Z]+\\s*)(\\|\\s*[a-zA-Z]+\\s*)*")) { 290 return Collections.singleton(-1); 291 } 292 return Arrays.stream(capabilitiesString.split("\\s*\\|\\s*")) 293 .map(String::trim) 294 .map(QnsUtils::getNetworkCapabilityFromString) 295 .collect(Collectors.toSet()); 296 } 297 298 /** 299 * Returns another transport type. 300 * @param transportType transport type 301 * @return another transport type of input parameter 302 */ 303 @AccessNetworkConstants.TransportType getOtherTransportType(@ccessNetworkConstants.TransportType int transportType)304 static int getOtherTransportType(@AccessNetworkConstants.TransportType int transportType) { 305 if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) { 306 return AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 307 } else if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { 308 return AccessNetworkConstants.TRANSPORT_TYPE_WLAN; 309 } 310 return AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 311 } 312 313 /** 314 * Convert network capabilities to string. 315 * 316 * <p>This is for debugging and logging purposes only. 317 * 318 * @param netCaps Network capabilities. 319 * @return Network capabilities in string format. 320 */ 321 @NonNull networkCapabilitiesToString( @etCapability @ullable Collection<Integer> netCaps)322 static String networkCapabilitiesToString( 323 @NetCapability @Nullable Collection<Integer> netCaps) { 324 if (netCaps == null || netCaps.isEmpty()) return ""; 325 return "[" 326 + netCaps.stream() 327 .map(QnsUtils::networkCapabilityToString) 328 .collect(Collectors.joining("|")) 329 + "]"; 330 } 331 332 /** 333 * Convert a network capability to string. 334 * 335 * <p>This is for debugging and logging purposes only. 336 * 337 * @param netCap Network capability. 338 * @return Network capability in string format. 339 */ 340 @NonNull networkCapabilityToString(@etCapability int netCap)341 static String networkCapabilityToString(@NetCapability int netCap) { 342 switch (netCap) { 343 case NetworkCapabilities.NET_CAPABILITY_MMS: 344 return "MMS"; 345 case NetworkCapabilities.NET_CAPABILITY_SUPL: 346 return "SUPL"; 347 case NetworkCapabilities.NET_CAPABILITY_DUN: 348 return "DUN"; 349 case NetworkCapabilities.NET_CAPABILITY_FOTA: 350 return "FOTA"; 351 case NetworkCapabilities.NET_CAPABILITY_IMS: 352 return "IMS"; 353 case NetworkCapabilities.NET_CAPABILITY_CBS: 354 return "CBS"; 355 case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P: 356 return "WIFI_P2P"; 357 case NetworkCapabilities.NET_CAPABILITY_IA: 358 return "IA"; 359 case NetworkCapabilities.NET_CAPABILITY_RCS: 360 return "RCS"; 361 case NetworkCapabilities.NET_CAPABILITY_XCAP: 362 return "XCAP"; 363 case NetworkCapabilities.NET_CAPABILITY_EIMS: 364 return "EIMS"; 365 case NetworkCapabilities.NET_CAPABILITY_NOT_METERED: 366 return "NOT_METERED"; 367 case NetworkCapabilities.NET_CAPABILITY_INTERNET: 368 return "INTERNET"; 369 case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED: 370 return "NOT_RESTRICTED"; 371 case NetworkCapabilities.NET_CAPABILITY_TRUSTED: 372 return "TRUSTED"; 373 case NetworkCapabilities.NET_CAPABILITY_NOT_VPN: 374 return "NOT_VPN"; 375 case NetworkCapabilities.NET_CAPABILITY_VALIDATED: 376 return "VALIDATED"; 377 case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL: 378 return "CAPTIVE_PORTAL"; 379 case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING: 380 return "NOT_ROAMING"; 381 case NetworkCapabilities.NET_CAPABILITY_FOREGROUND: 382 return "FOREGROUND"; 383 case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED: 384 return "NOT_CONGESTED"; 385 case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED: 386 return "NOT_SUSPENDED"; 387 case NetworkCapabilities.NET_CAPABILITY_OEM_PAID: 388 return "OEM_PAID"; 389 case NetworkCapabilities.NET_CAPABILITY_MCX: 390 return "MCX"; 391 case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY: 392 return "PARTIAL_CONNECTIVITY"; 393 case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED: 394 return "TEMPORARILY_NOT_METERED"; 395 case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE: 396 return "OEM_PRIVATE"; 397 case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL: 398 return "VEHICLE_INTERNAL"; 399 case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED: 400 return "NOT_VCN_MANAGED"; 401 case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE: 402 return "ENTERPRISE"; 403 case NetworkCapabilities.NET_CAPABILITY_VSIM: 404 return "VSIM"; 405 case NetworkCapabilities.NET_CAPABILITY_BIP: 406 return "BIP"; 407 case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT: 408 return "HEAD_UNIT"; 409 case NetworkCapabilities.NET_CAPABILITY_MMTEL: 410 return "MMTEL"; 411 case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY: 412 return "PRIORITIZE_LATENCY"; 413 case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH: 414 return "PRIORITIZE_BANDWIDTH"; 415 default: 416 return "Unknown(" + netCap + ")"; 417 } 418 } 419 420 /** 421 * Get the network capability from the string. 422 * 423 * @param capabilityString The capability in string format 424 * @return The network capability. -1 if not found. 425 */ 426 @NetCapability getNetworkCapabilityFromString(@onNull String capabilityString)427 static int getNetworkCapabilityFromString(@NonNull String capabilityString) { 428 switch (capabilityString.toUpperCase(Locale.ROOT)) { 429 case "MMS": 430 return NetworkCapabilities.NET_CAPABILITY_MMS; 431 case "SUPL": 432 return NetworkCapabilities.NET_CAPABILITY_SUPL; 433 case "DUN": 434 return NetworkCapabilities.NET_CAPABILITY_DUN; 435 case "FOTA": 436 return NetworkCapabilities.NET_CAPABILITY_FOTA; 437 case "IMS": 438 return NetworkCapabilities.NET_CAPABILITY_IMS; 439 case "CBS": 440 return NetworkCapabilities.NET_CAPABILITY_CBS; 441 case "XCAP": 442 return NetworkCapabilities.NET_CAPABILITY_XCAP; 443 case "EIMS": 444 return NetworkCapabilities.NET_CAPABILITY_EIMS; 445 case "INTERNET": 446 return NetworkCapabilities.NET_CAPABILITY_INTERNET; 447 case "MCX": 448 return NetworkCapabilities.NET_CAPABILITY_MCX; 449 case "VSIM": 450 return NetworkCapabilities.NET_CAPABILITY_VSIM; 451 case "BIP": 452 return NetworkCapabilities.NET_CAPABILITY_BIP; 453 case "ENTERPRISE": 454 return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; 455 case "PRIORITIZE_BANDWIDTH": 456 return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH; 457 case "PRIORITIZE_LATENCY": 458 return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY; 459 default: 460 return -1; 461 } 462 } 463 464 /** 465 * Get the network capability from the apn type. 466 * 467 * @param apnType apn type. 468 * @return network capability 469 */ 470 @NetCapability getNetCapabilityFromApnType(int apnType)471 static int getNetCapabilityFromApnType(int apnType) { 472 switch (apnType) { 473 case ApnSetting.TYPE_IMS: 474 return NetworkCapabilities.NET_CAPABILITY_IMS; 475 case ApnSetting.TYPE_EMERGENCY: 476 return NetworkCapabilities.NET_CAPABILITY_EIMS; 477 case ApnSetting.TYPE_MMS: 478 return NetworkCapabilities.NET_CAPABILITY_MMS; 479 case ApnSetting.TYPE_XCAP: 480 return NetworkCapabilities.NET_CAPABILITY_XCAP; 481 case ApnSetting.TYPE_CBS: 482 return NetworkCapabilities.NET_CAPABILITY_CBS; 483 default: 484 throw new IllegalArgumentException("Unsupported apnType: " + apnType); 485 } 486 } 487 488 /** 489 * Get the apn type from the network capability. 490 * 491 * @param netCapability network capability. 492 * @return apn type. 493 */ getApnTypeFromNetCapability(@etCapability int netCapability)494 static int getApnTypeFromNetCapability(@NetCapability int netCapability) { 495 switch (netCapability) { 496 case NetworkCapabilities.NET_CAPABILITY_IMS: 497 return ApnSetting.TYPE_IMS; 498 case NetworkCapabilities.NET_CAPABILITY_EIMS: 499 return ApnSetting.TYPE_EMERGENCY; 500 case NetworkCapabilities.NET_CAPABILITY_MMS: 501 return ApnSetting.TYPE_MMS; 502 case NetworkCapabilities.NET_CAPABILITY_XCAP: 503 return ApnSetting.TYPE_XCAP; 504 case NetworkCapabilities.NET_CAPABILITY_CBS: 505 return ApnSetting.TYPE_CBS; 506 default: 507 throw new IllegalArgumentException("Unsupported netCapability: " + netCapability); 508 } 509 } 510 511 /** 512 * Convert a network capability to string. 513 * 514 * <p>This is for debugging and logging purposes only. 515 * 516 * @param netCapability Network capability. 517 * @return Network capability in string format. 518 */ 519 @NonNull getNameOfNetCapability(@etCapability int netCapability)520 static String getNameOfNetCapability(@NetCapability int netCapability) { 521 switch (netCapability) { 522 case NetworkCapabilities.NET_CAPABILITY_IMS: 523 return "ims"; 524 case NetworkCapabilities.NET_CAPABILITY_EIMS: 525 return "eims"; 526 case NetworkCapabilities.NET_CAPABILITY_MMS: 527 return "mms"; 528 case NetworkCapabilities.NET_CAPABILITY_CBS: 529 return "cbs"; 530 case NetworkCapabilities.NET_CAPABILITY_XCAP: 531 return "xcap"; 532 default: 533 throw new IllegalArgumentException("Unsupported netCapability: " + netCapability); 534 } 535 } 536 537 /** 538 * Get the network capability from the string. 539 * 540 * @param types string array of APN types. 541 * @return list of Network Capabilities 542 */ 543 @NetCapability getNetCapabilitiesFromApnTypesString(@onNull String[] types)544 static List<Integer> getNetCapabilitiesFromApnTypesString(@NonNull String[] types) { 545 int apnTypesBitmask = 0; 546 for (String str : types) { 547 apnTypesBitmask |= ApnSetting.getApnTypeInt(str); 548 } 549 return getNetCapabilitiesFromApnTypeBitmask(apnTypesBitmask); 550 } 551 552 /** 553 * Get a list of supported network capabilities from apnTypeBitmask 554 * 555 * @param apnTypeBitmask bitmask of APN types. 556 * @return list of Network Capabilities 557 */ getNetCapabilitiesFromApnTypeBitmask(int apnTypeBitmask)558 static List<Integer> getNetCapabilitiesFromApnTypeBitmask(int apnTypeBitmask) { 559 List<Integer> netCapabilities = new ArrayList<>(); 560 List<Integer> apnTypes = getApnTypes(apnTypeBitmask); 561 for (int apnType : apnTypes) { 562 try { 563 netCapabilities.add(getNetCapabilityFromApnType(apnType)); 564 } catch (IllegalArgumentException e) { 565 continue; 566 } 567 } 568 return netCapabilities; 569 } 570 readQnsDefaultConfigFromAssets(Context context, int qnsCarrierID)571 static PersistableBundle readQnsDefaultConfigFromAssets(Context context, int qnsCarrierID) { 572 573 if (qnsCarrierID == TelephonyManager.UNKNOWN_CARRIER_ID) { 574 return null; 575 } 576 577 return readConfigFromAssets(context, CARRIER_ID_PREFIX + qnsCarrierID + "_"); 578 } 579 getConfig( PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle, String key)580 static synchronized <T> T getConfig( 581 PersistableBundle carrierConfigBundle, 582 PersistableBundle assetConfigBundle, 583 String key) { 584 585 // TODO: PersistableBundle.get is deprecated. 586 if (carrierConfigBundle == null || carrierConfigBundle.get(key) == null) { 587 log("key not set in pb file: " + key); 588 589 if (assetConfigBundle == null || assetConfigBundle.get(key) == null) { 590 return (T) getDefaultValueForKey(key); 591 } else { 592 return (T) assetConfigBundle.get(key); 593 } 594 } 595 return (T) carrierConfigBundle.get(key); 596 } 597 getDefaultValueForKey(String key)598 static synchronized <T> T getDefaultValueForKey(String key) { 599 switch (key) { 600 case QnsCarrierConfigManager.KEY_QNS_SUPPORT_WFC_DURING_AIRPLANE_MODE_BOOL: 601 case QnsCarrierConfigManager.KEY_BLOCK_IPV6_ONLY_WIFI_BOOL: 602 case CarrierConfigManager.ImsVoice.KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL: 603 return (T) Boolean.valueOf(true); 604 case QnsCarrierConfigManager 605 .KEY_QNS_ALLOW_VIDEO_OVER_IWLAN_WITH_CELLULAR_LIMITED_CASE_BOOL: 606 case QnsCarrierConfigManager.KEY_QNS_HO_GUARDING_BY_PREFERENCE_BOOL: 607 case QnsCarrierConfigManager.KEY_QNS_SUPPORT_SERVICE_BARRING_CHECK_BOOL: 608 case QnsCarrierConfigManager 609 .KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL: 610 case QnsCarrierConfigManager.KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL_BOOL: 611 case QnsCarrierConfigManager.KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL: 612 case QnsCarrierConfigManager 613 .KEY_QNS_ROVE_OUT_POLICY_WITH_WIFI_BAD_GUARDTIMER_CONDITIONS_BOOL: 614 case QnsCarrierConfigManager.KEY_QNS_ALLOW_IMS_OVER_IWLAN_CELLULAR_LIMITED_CASE_BOOL: 615 case QnsCarrierConfigManager.KEY_BLOCK_IWLAN_IN_INTERNATIONAL_ROAMING_WITHOUT_WWAN_BOOL: 616 case QnsCarrierConfigManager 617 .KEY_IN_CALL_HO_DECISION_WLAN_TO_WWAN_WITHOUT_VOPS_CONDITION_BOOL: 618 return (T) Boolean.valueOf(false); 619 case QnsCarrierConfigManager.KEY_SIP_DIALOG_SESSION_POLICY_INT: 620 return (T) Integer.valueOf(QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE); 621 case QnsCarrierConfigManager.KEY_QNS_CELLULAR_SS_THRESHOLDBACKHAUL_TIMER_MS_INT: 622 return (T) Integer.valueOf(QnsConstants.KEY_DEFAULT_VALUE); 623 case QnsCarrierConfigManager.KEY_QNS_WIFI_RSSI_THRESHOLDBACKHAUL_TIMER_MS_INT: 624 return (T) Integer.valueOf(QnsConstants.DEFAULT_WIFI_BACKHAUL_TIMER); 625 case QnsCarrierConfigManager.KEY_QNS_IMS_TRANSPORT_TYPE_INT: 626 return (T) Integer.valueOf(QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH); 627 case QnsCarrierConfigManager.KEY_QNS_MMS_TRANSPORT_TYPE_INT: 628 case QnsCarrierConfigManager.KEY_QNS_CBS_TRANSPORT_TYPE_INT: 629 case QnsCarrierConfigManager.KEY_QNS_SOS_TRANSPORT_TYPE_INT: 630 return (T) Integer.valueOf(QnsConstants.TRANSPORT_TYPE_ALLOWED_WWAN); 631 case QnsCarrierConfigManager.KEY_QNS_XCAP_RAT_PREFERENCE_INT: 632 case QnsCarrierConfigManager.KEY_QNS_SOS_RAT_PREFERENCE_INT: 633 case QnsCarrierConfigManager.KEY_QNS_MMS_RAT_PREFERENCE_INT: 634 case QnsCarrierConfigManager.KEY_QNS_CBS_RAT_PREFERENCE_INT: 635 return (T) Integer.valueOf(QnsConstants.RAT_PREFERENCE_DEFAULT); 636 case KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT: 637 return (T) Integer.valueOf(CONFIG_DEFAULT_VOWIFI_REGISTATION_TIMER); 638 case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_JITTER_THRESHOLD_MILLIS_INT: 639 case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT: 640 return (T) Integer.valueOf(QnsConstants.INVALID_VALUE); 641 case QnsCarrierConfigManager.KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT: 642 return (T) Integer.valueOf(QnsConstants.KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS); 643 case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG: 644 return (T) Long.valueOf(QnsConstants.INVALID_VALUE); 645 case QnsCarrierConfigManager 646 .KEY_QNS_IN_CALL_ROVEIN_ALLOWED_COUNT_AND_FALLBACK_REASON_INT_ARRAY: 647 return (T) 648 new int[] { 649 QnsConstants.MAX_COUNT_INVALID, QnsConstants.FALLBACK_REASON_INVALID 650 }; 651 case QnsCarrierConfigManager 652 .KEY_WAITING_TIME_FOR_PREFERRED_TRANSPORT_WHEN_POWER_ON_INT_ARRAY: 653 case QnsCarrierConfigManager.KEY_NON_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY: 654 case QnsCarrierConfigManager.KEY_NON_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY: 655 return (T) 656 new int[] {QnsConstants.KEY_DEFAULT_VALUE, QnsConstants.KEY_DEFAULT_VALUE}; 657 case QnsCarrierConfigManager.KEY_QNS_IMS_NETWORK_ENABLE_HO_HYSTERESIS_TIMER_INT: 658 return (T) Integer.valueOf(QnsConstants.COVERAGE_BOTH); 659 case QnsCarrierConfigManager 660 .KEY_QNS_HO_RESTRICT_TIME_WITH_LOW_RTP_QUALITY_MILLIS_INT_ARRAY: 661 return (T) 662 new int[] { 663 QnsConstants.KEY_DEFAULT_IWLAN_AVOID_TIME_LOW_RTP_QUALITY_MILLIS, 664 QnsConstants.KEY_DEFAULT_WWAN_AVOID_TIME_LOW_RTP_QUALITY_MILLIS, 665 }; 666 case QnsCarrierConfigManager.KEY_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY: 667 case QnsCarrierConfigManager.KEY_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY: 668 return (T) 669 new int[] { 670 QnsConstants.KEY_DEFAULT_HYST_TIMER, 671 QnsConstants.KEY_DEFAULT_HYST_TIMER, 672 QnsConstants.KEY_DEFAULT_HYST_TIMER 673 }; 674 case QnsCarrierConfigManager.KEY_MINIMUM_HANDOVER_GUARDING_TIMER_MS_INT: 675 return (T) Integer.valueOf(QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER); 676 case QnsCarrierConfigManager 677 .KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY: 678 return (T) new int[] {}; 679 case QnsCarrierConfigManager.KEY_IMS_CELLULAR_ALLOWED_RAT_STRING_ARRAY: 680 return (T) new String[] {"LTE", "NR"}; 681 case QnsCarrierAnspSupportConfig.KEY_IDLE_NGRAN_SSRSRP_INT_ARRAY: 682 case QnsCarrierAnspSupportConfig.KEY_VOICE_NGRAN_SSRSRP_INT_ARRAY: 683 case QnsCarrierAnspSupportConfig.KEY_VIDEO_NGRAN_SSRSRP_INT_ARRAY: 684 return (T) 685 new int[] { 686 QnsConstants.KEY_DEFAULT_THRESHOLD_SSRSRP_GOOD, 687 QnsConstants.KEY_DEFAULT_THRESHOLD_SSRSRP_BAD, 688 QnsCarrierConfigManager.QnsConfigArray.INVALID 689 }; 690 case QnsCarrierAnspSupportConfig.KEY_IDLE_EUTRAN_RSRP_INT_ARRAY: 691 case QnsCarrierAnspSupportConfig.KEY_VOICE_EUTRAN_RSRP_INT_ARRAY: 692 case QnsCarrierAnspSupportConfig.KEY_VIDEO_EUTRAN_RSRP_INT_ARRAY: 693 return (T) 694 new int[] { 695 QnsConstants.KEY_DEFAULT_THRESHOLD_RSRP_GOOD, 696 QnsConstants.KEY_DEFAULT_THRESHOLD_RSRP_BAD, 697 QnsCarrierConfigManager.QnsConfigArray.INVALID 698 }; 699 case QnsCarrierAnspSupportConfig.KEY_IDLE_UTRAN_RSCP_INT_ARRAY: 700 case QnsCarrierAnspSupportConfig.KEY_VOICE_UTRAN_RSCP_INT_ARRAY: 701 case QnsCarrierAnspSupportConfig.KEY_VIDEO_UTRAN_RSCP_INT_ARRAY: 702 return (T) 703 new int[] { 704 QnsConstants.KEY_DEFAULT_THRESHOLD_RSCP_GOOD, 705 QnsConstants.KEY_DEFAULT_THRESHOLD_RSCP_BAD, 706 QnsCarrierConfigManager.QnsConfigArray.INVALID 707 }; 708 case QnsCarrierAnspSupportConfig.KEY_IDLE_GERAN_RSSI_INT_ARRAY: 709 case QnsCarrierAnspSupportConfig.KEY_VOICE_GERAN_RSSI_INT_ARRAY: 710 case QnsCarrierAnspSupportConfig.KEY_VIDEO_GERAN_RSSI_INT_ARRAY: 711 return (T) 712 new int[] { 713 QnsConstants.KEY_DEFAULT_THRESHOLD_GERAN_RSSI_GOOD, 714 QnsConstants.KEY_DEFAULT_THRESHOLD_GERAN_RSSI_BAD, 715 QnsCarrierConfigManager.QnsConfigArray.INVALID 716 }; 717 case QnsCarrierAnspSupportConfig.KEY_IDLE_WIFI_RSSI_INT_ARRAY: 718 case QnsCarrierAnspSupportConfig.KEY_VOICE_WIFI_RSSI_INT_ARRAY: 719 case QnsCarrierAnspSupportConfig.KEY_VIDEO_WIFI_RSSI_INT_ARRAY: 720 return (T) 721 new int[] { 722 QnsConstants.KEY_DEFAULT_THRESHOLD_WIFI_RSSI_GOOD, 723 QnsConstants.KEY_DEFAULT_THRESHOLD_WIFI_RSSI_BAD 724 }; 725 case QnsCarrierAnspSupportConfig.KEY_OVERRIDE_WIFI_PREF_IDLE_WIFI_RSSI_INT_ARRAY: 726 case QnsCarrierAnspSupportConfig.KEY_OVERRIDE_WIFI_PREF_VOICE_WIFI_RSSI_INT_ARRAY: 727 case QnsCarrierAnspSupportConfig.KEY_OVERRIDE_WIFI_PREF_VIDEO_WIFI_RSSI_INT_ARRAY: 728 case CarrierConfigManager.Ims.KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY: 729 return (T) new int[] {}; 730 case QnsCarrierConfigManager.KEY_QNS_WLAN_RTT_BACKHAUL_CHECK_ON_ICMP_PING_STRING: 731 return (T) ""; 732 case QnsCarrierConfigManager 733 .KEY_QNS_FALLBACK_ON_INITIAL_CONNECTION_FAILURE_STRING_ARRAY: 734 return (T) new String[] {}; 735 default: 736 break; 737 } 738 return (T) null; 739 } 740 getConfigCarrierId(Context context, int slotId)741 static synchronized int getConfigCarrierId(Context context, int slotId) { 742 TelephonyManager tm = context.getSystemService(TelephonyManager.class); 743 tm = tm.createForSubscriptionId(QnsUtils.getSubId(context, slotId)); 744 return tm.getSimCarrierId(); 745 } 746 getAssetFileName(Context context, String carrierIDConfig)747 private static String getAssetFileName(Context context, String carrierIDConfig) { 748 String[] configFileNameList; 749 try { 750 configFileNameList = context.getAssets().list(""); 751 for (String fileName : configFileNameList) { 752 if (fileName.startsWith(carrierIDConfig)) { 753 log("matched file: " + fileName); 754 return fileName; 755 } 756 } 757 } catch (Exception e) { 758 loge("getFileName, can't find " + carrierIDConfig + " asset"); 759 } 760 return null; 761 } 762 readConfigFromAssets(Context context, String carrierIDConfig)763 private static PersistableBundle readConfigFromAssets(Context context, String carrierIDConfig) { 764 PersistableBundle bundleFromAssets = new PersistableBundle(); 765 766 String fileName = getAssetFileName(context, carrierIDConfig); 767 InputStream inputStream = null; 768 InputStreamReader inputStreamReader = null; 769 try { 770 inputStream = context.getAssets().open(fileName); 771 inputStreamReader = new InputStreamReader(inputStream); 772 Stream<String> streamOfString = new BufferedReader(inputStreamReader).lines(); 773 String streamToString = streamOfString.collect(Collectors.joining()); 774 775 String configTag = "carrier_config"; 776 int begin = streamToString.indexOf(configTag); 777 int end = streamToString.lastIndexOf(configTag) + configTag.length(); 778 String bundleString = "<" + streamToString.substring(begin, end) + ">"; 779 780 InputStream targetStream = new ByteArrayInputStream(bundleString.getBytes()); 781 bundleFromAssets = PersistableBundle.readFromStream(targetStream); 782 783 log("bundleFromAssets created : " + bundleFromAssets); 784 785 } catch (Exception e) { 786 loge("readConfigFromAssets, e: " + e); 787 } finally { 788 if (inputStreamReader != null) { 789 try { 790 inputStreamReader.close(); 791 } catch (Exception e) { 792 loge("inputStreamReader.close e:" + e); 793 } 794 } 795 if (inputStream != null) { 796 try { 797 inputStream.close(); 798 } catch (Exception e) { 799 loge("inputStream.close e:" + e); 800 } 801 } 802 } 803 return bundleFromAssets; 804 } 805 loge(String log)806 protected static void loge(String log) { 807 Log.e(QnsUtils.class.getSimpleName(), log); 808 } 809 log(String log)810 protected static void log(String log) { 811 Log.d(QnsUtils.class.getSimpleName(), log); 812 } 813 814 protected static class QnsExecutor implements Executor { 815 private final Handler mHandler; 816 QnsExecutor(Handler handler)817 QnsExecutor(Handler handler) { 818 mHandler = handler; 819 } 820 821 @Override execute(Runnable command)822 public void execute(Runnable command) { 823 if (!mHandler.post(command)) { 824 throw new RejectedExecutionException(mHandler + " is shutting down"); 825 } 826 } 827 } 828 } 829