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