• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.internal.telephony.data;
18 
19 import android.annotation.CurrentTimeMillisLong;
20 import android.annotation.ElapsedRealtimeLong;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.net.NetworkAgent;
24 import android.net.NetworkCapabilities;
25 import android.os.SystemClock;
26 import android.telephony.AccessNetworkConstants;
27 import android.telephony.AccessNetworkConstants.AccessNetworkType;
28 import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
29 import android.telephony.AccessNetworkConstants.TransportType;
30 import android.telephony.Annotation.ConnectivityTransport;
31 import android.telephony.Annotation.DataActivityType;
32 import android.telephony.Annotation.NetCapability;
33 import android.telephony.Annotation.NetworkType;
34 import android.telephony.Annotation.ValidationStatus;
35 import android.telephony.TelephonyManager;
36 import android.telephony.data.ApnSetting;
37 import android.telephony.data.ApnSetting.ApnType;
38 import android.telephony.data.DataCallResponse;
39 import android.telephony.data.DataCallResponse.LinkStatus;
40 import android.telephony.ims.feature.ImsFeature;
41 import android.util.ArrayMap;
42 
43 import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
44 import com.android.internal.telephony.flags.FeatureFlags;
45 import com.android.telephony.Rlog;
46 
47 import java.text.SimpleDateFormat;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.List;
53 import java.util.Locale;
54 import java.util.Map;
55 import java.util.Set;
56 import java.util.stream.Collectors;
57 
58 /**
59  * This class contains all the utility methods used by telephony data stack.
60  */
61 public class DataUtils {
62     public static final int NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED = 37;
63     /** The time format for converting time to readable string. */
64     private static final SimpleDateFormat TIME_FORMAT =
65             new SimpleDateFormat("HH:mm:ss.SSS", Locale.US);
66     private static final String TAG = "DataUtils";
67 
68     /**
69      * Get the network capability from the string.
70      *
71      * @param capabilityString The capability in string format
72      * @return The network capability. -1 if not found.
73      */
74     @NetCapability
getNetworkCapabilityFromString(@onNull String capabilityString)75     public static int getNetworkCapabilityFromString(@NonNull String capabilityString) {
76         return switch (capabilityString.toUpperCase(Locale.ROOT)) {
77             case "MMS" -> NetworkCapabilities.NET_CAPABILITY_MMS;
78             case "SUPL" -> NetworkCapabilities.NET_CAPABILITY_SUPL;
79             case "DUN" -> NetworkCapabilities.NET_CAPABILITY_DUN;
80             case "FOTA" -> NetworkCapabilities.NET_CAPABILITY_FOTA;
81             case "IMS" -> NetworkCapabilities.NET_CAPABILITY_IMS;
82             case "CBS" -> NetworkCapabilities.NET_CAPABILITY_CBS;
83             case "XCAP" -> NetworkCapabilities.NET_CAPABILITY_XCAP;
84             case "EIMS" -> NetworkCapabilities.NET_CAPABILITY_EIMS;
85             case "INTERNET" -> NetworkCapabilities.NET_CAPABILITY_INTERNET;
86             case "MCX" -> NetworkCapabilities.NET_CAPABILITY_MCX;
87             case "VSIM" -> NetworkCapabilities.NET_CAPABILITY_VSIM;
88             case "BIP" -> NetworkCapabilities.NET_CAPABILITY_BIP;
89             case "ENTERPRISE" -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
90             case "PRIORITIZE_BANDWIDTH" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
91             case "PRIORITIZE_LATENCY" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY;
92             case "RCS" -> NetworkCapabilities.NET_CAPABILITY_RCS;
93             default -> {
94                 loge("Illegal network capability: " + capabilityString);
95                 yield -1;
96             }
97         };
98     }
99 
100     /**
101      * Get Set of network capabilities from string joined by {@code |}, space is ignored.
102      * If input string contains unknown capability or malformatted(e.g. empty string), -1 is
103      * included in the returned set.
104      *
105      * @param capabilitiesString capability strings joined by {@code |}
106      * @return Set of capabilities
107      */
108     @NetCapability
getNetworkCapabilitiesFromString( @onNull String capabilitiesString)109     public static Set<Integer> getNetworkCapabilitiesFromString(
110             @NonNull String capabilitiesString) {
111         // e.g. "IMS|" is not allowed
112         if (!capabilitiesString.matches("(\\s*[a-zA-Z_]+\\s*)(\\|\\s*[a-zA-Z_]+\\s*)*")) {
113             return Collections.singleton(-1);
114         }
115         return Arrays.stream(capabilitiesString.split("\\s*\\|\\s*"))
116                 .map(String::trim)
117                 .map(DataUtils::getNetworkCapabilityFromString)
118                 .collect(Collectors.toSet());
119     }
120 
121     /**
122      * Convert a network capability to string.
123      * <p>
124      * This is for debugging and logging purposes only.
125      *
126      * @param netCap Network capability.
127      * @return Network capability in string format.
128      */
129     @NonNull
networkCapabilityToString(@etCapability int netCap)130     public static String networkCapabilityToString(@NetCapability int netCap) {
131         return switch (netCap) {
132             case NetworkCapabilities.NET_CAPABILITY_MMS -> "MMS";
133             case NetworkCapabilities.NET_CAPABILITY_SUPL -> "SUPL";
134             case NetworkCapabilities.NET_CAPABILITY_DUN -> "DUN";
135             case NetworkCapabilities.NET_CAPABILITY_FOTA -> "FOTA";
136             case NetworkCapabilities.NET_CAPABILITY_IMS -> "IMS";
137             case NetworkCapabilities.NET_CAPABILITY_CBS -> "CBS";
138             case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P -> "WIFI_P2P";
139             case NetworkCapabilities.NET_CAPABILITY_IA -> "IA";
140             case NetworkCapabilities.NET_CAPABILITY_RCS -> "RCS";
141             case NetworkCapabilities.NET_CAPABILITY_XCAP -> "XCAP";
142             case NetworkCapabilities.NET_CAPABILITY_EIMS -> "EIMS";
143             case NetworkCapabilities.NET_CAPABILITY_NOT_METERED -> "NOT_METERED";
144             case NetworkCapabilities.NET_CAPABILITY_INTERNET -> "INTERNET";
145             case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED -> "NOT_RESTRICTED";
146             case NetworkCapabilities.NET_CAPABILITY_TRUSTED -> "TRUSTED";
147             case NetworkCapabilities.NET_CAPABILITY_NOT_VPN -> "NOT_VPN";
148             case NetworkCapabilities.NET_CAPABILITY_VALIDATED -> "VALIDATED";
149             case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -> "CAPTIVE_PORTAL";
150             case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING -> "NOT_ROAMING";
151             case NetworkCapabilities.NET_CAPABILITY_FOREGROUND -> "FOREGROUND";
152             case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED -> "NOT_CONGESTED";
153             case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED -> "NOT_SUSPENDED";
154             case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> "OEM_PAID";
155             case NetworkCapabilities.NET_CAPABILITY_MCX -> "MCX";
156             case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY -> "PARTIAL_CONNECTIVITY";
157             case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED ->
158                     "TEMPORARILY_NOT_METERED";
159             case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> "OEM_PRIVATE";
160             case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL -> "VEHICLE_INTERNAL";
161             case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED -> "NOT_VCN_MANAGED";
162             case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> "ENTERPRISE";
163             case NetworkCapabilities.NET_CAPABILITY_VSIM -> "VSIM";
164             case NetworkCapabilities.NET_CAPABILITY_BIP -> "BIP";
165             case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT -> "HEAD_UNIT";
166             case NetworkCapabilities.NET_CAPABILITY_MMTEL -> "MMTEL";
167             case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY -> "PRIORITIZE_LATENCY";
168             case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH -> "PRIORITIZE_BANDWIDTH";
169             case NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED -> "NOT_BANDWIDTH_CONSTRAINED";
170             default -> {
171                 loge("Unknown network capability(" + netCap + ")");
172                 yield "Unknown(" + netCap + ")";
173             }
174         };
175     }
176 
177     /**
178      * Concat an array of {@link NetworkCapabilities.Transport} in string format.
179      *
180      * @param transports an array of connectivity transports
181      * @return a string of the array of transports.
182      */
183     @NonNull
184     public static String connectivityTransportsToString(
185             @NonNull @ConnectivityTransport int[] transports) {
186         return Arrays.stream(transports).mapToObj(DataUtils::connectivityTransportToString)
187                 .collect(Collectors.joining("|"));
188     }
189 
190     /**
191      * Convert a {@link NetworkCapabilities.Transport} to a string.
192      *
193      * @param transport the connectivity transport
194      * @return the transport in string
195      */
196     @NonNull
197     public static String connectivityTransportToString(
198             @ConnectivityTransport int transport) {
199         return switch (transport) {
200             case NetworkCapabilities.TRANSPORT_CELLULAR -> "CELLULAR";
201             case NetworkCapabilities.TRANSPORT_WIFI -> "WIFI";
202             case NetworkCapabilities.TRANSPORT_BLUETOOTH -> "BLUETOOTH";
203             case NetworkCapabilities.TRANSPORT_ETHERNET -> "ETHERNET";
204             case NetworkCapabilities.TRANSPORT_VPN -> "VPN";
205             case NetworkCapabilities.TRANSPORT_WIFI_AWARE -> "WIFI_AWARE";
206             case NetworkCapabilities.TRANSPORT_LOWPAN -> "LOWPAN";
207             case NetworkCapabilities.TRANSPORT_TEST -> "TEST";
208             case NetworkCapabilities.TRANSPORT_USB -> "USB";
209             case NetworkCapabilities.TRANSPORT_THREAD -> "THREAD";
210             case NetworkCapabilities.TRANSPORT_SATELLITE -> "SATELLITE";
211             default -> "Unknown(" + transport + ")";
212         };
213     }
214 
215     /**
216      * Convert network capabilities to string.
217      * <p>
218      * This is for debugging and logging purposes only.
219      *
220      * @param netCaps Network capabilities.
221      * @return Network capabilities in string format.
222      */
223     @NonNull
224     public static String networkCapabilitiesToString(
225             @NetCapability @Nullable Collection<Integer> netCaps) {
226         if (netCaps == null || netCaps.isEmpty()) return "";
227         return "[" + netCaps.stream()
228                 .map(DataUtils::networkCapabilityToString)
229                 .collect(Collectors.joining("|")) + "]";
230     }
231 
232     /**
233      * Convert network capabilities to string.
234      * <p>
235      * This is for debugging and logging purposes only.
236      *
237      * @param netCaps Network capabilities.
238      * @return Network capabilities in string format.
239      */
240     @NonNull
241     public static String networkCapabilitiesToString(@NetCapability int[] netCaps) {
242         if (netCaps == null) return "";
243         return "[" + Arrays.stream(netCaps)
244                 .mapToObj(DataUtils::networkCapabilityToString)
245                 .collect(Collectors.joining("|")) + "]";
246     }
247 
248     /**
249      * Convert the validation status to string.
250      *
251      * @param status The validation status.
252      * @return The validation status in string format.
253      */
254     @NonNull
255     public static String validationStatusToString(@ValidationStatus int status) {
256         return switch (status) {
257             case NetworkAgent.VALIDATION_STATUS_VALID -> "VALID";
258             case NetworkAgent.VALIDATION_STATUS_NOT_VALID -> "INVALID";
259             default -> {
260                 loge("Unknown validation status(" + status + ")");
261                 yield "UNKNOWN(" + status + ")";
262             }
263         };
264     }
265 
266     /**
267      * Convert network capability into APN type.
268      *
269      * @param networkCapability Network capability.
270      * @return APN type.
271      */
272     @ApnType
273     public static int networkCapabilityToApnType(@NetCapability int networkCapability) {
274         return switch (networkCapability) {
275             case NetworkCapabilities.NET_CAPABILITY_MMS -> ApnSetting.TYPE_MMS;
276             case NetworkCapabilities.NET_CAPABILITY_SUPL -> ApnSetting.TYPE_SUPL;
277             case NetworkCapabilities.NET_CAPABILITY_DUN -> ApnSetting.TYPE_DUN;
278             case NetworkCapabilities.NET_CAPABILITY_FOTA -> ApnSetting.TYPE_FOTA;
279             case NetworkCapabilities.NET_CAPABILITY_IMS -> ApnSetting.TYPE_IMS;
280             case NetworkCapabilities.NET_CAPABILITY_CBS -> ApnSetting.TYPE_CBS;
281             case NetworkCapabilities.NET_CAPABILITY_XCAP -> ApnSetting.TYPE_XCAP;
282             case NetworkCapabilities.NET_CAPABILITY_EIMS -> ApnSetting.TYPE_EMERGENCY;
283             case NetworkCapabilities.NET_CAPABILITY_INTERNET -> ApnSetting.TYPE_DEFAULT;
284             case NetworkCapabilities.NET_CAPABILITY_MCX -> ApnSetting.TYPE_MCX;
285             case NetworkCapabilities.NET_CAPABILITY_IA -> ApnSetting.TYPE_IA;
286             case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> ApnSetting.TYPE_ENTERPRISE;
287             case NetworkCapabilities.NET_CAPABILITY_VSIM -> ApnSetting.TYPE_VSIM;
288             case NetworkCapabilities.NET_CAPABILITY_BIP -> ApnSetting.TYPE_BIP;
289             case NetworkCapabilities.NET_CAPABILITY_RCS -> ApnSetting.TYPE_RCS;
290             case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> ApnSetting.TYPE_OEM_PAID;
291             case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> ApnSetting.TYPE_OEM_PRIVATE;
292             default -> ApnSetting.TYPE_NONE;
293         };
294     }
295 
296     /**
297      * Convert APN type to capability.
298      *
299      * @param apnType APN type.
300      * @return Network capability.
301      */
302     @NetCapability
303     public static int apnTypeToNetworkCapability(@ApnType int apnType) {
304         return switch (apnType) {
305             case ApnSetting.TYPE_MMS -> NetworkCapabilities.NET_CAPABILITY_MMS;
306             case ApnSetting.TYPE_SUPL -> NetworkCapabilities.NET_CAPABILITY_SUPL;
307             case ApnSetting.TYPE_DUN -> NetworkCapabilities.NET_CAPABILITY_DUN;
308             case ApnSetting.TYPE_FOTA -> NetworkCapabilities.NET_CAPABILITY_FOTA;
309             case ApnSetting.TYPE_IMS -> NetworkCapabilities.NET_CAPABILITY_IMS;
310             case ApnSetting.TYPE_CBS -> NetworkCapabilities.NET_CAPABILITY_CBS;
311             case ApnSetting.TYPE_XCAP -> NetworkCapabilities.NET_CAPABILITY_XCAP;
312             case ApnSetting.TYPE_EMERGENCY -> NetworkCapabilities.NET_CAPABILITY_EIMS;
313             case ApnSetting.TYPE_DEFAULT -> NetworkCapabilities.NET_CAPABILITY_INTERNET;
314             case ApnSetting.TYPE_MCX -> NetworkCapabilities.NET_CAPABILITY_MCX;
315             case ApnSetting.TYPE_IA -> NetworkCapabilities.NET_CAPABILITY_IA;
316             case ApnSetting.TYPE_BIP -> NetworkCapabilities.NET_CAPABILITY_BIP;
317             case ApnSetting.TYPE_VSIM -> NetworkCapabilities.NET_CAPABILITY_VSIM;
318             case ApnSetting.TYPE_ENTERPRISE -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
319             case ApnSetting.TYPE_RCS -> NetworkCapabilities.NET_CAPABILITY_RCS;
320             case ApnSetting.TYPE_OEM_PAID -> NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
321             case ApnSetting.TYPE_OEM_PRIVATE -> NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
322             default -> -1;
323         };
324     }
325 
326     /**
327      * Convert network type to access network type.
328      *
329      * @param networkType The network type.
330      * @return The access network type.
331      */
332     @RadioAccessNetworkType
333     public static int networkTypeToAccessNetworkType(@NetworkType int networkType) {
334         return switch (networkType) {
335             case TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE,
336                     TelephonyManager.NETWORK_TYPE_GSM ->
337                     AccessNetworkType.GERAN;
338             case TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA,
339                     TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA,
340                     TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_TD_SCDMA ->
341                     AccessNetworkType.UTRAN;
342             case TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EVDO_0,
343                     TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B,
344                     TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_EHRPD ->
345                     AccessNetworkType.CDMA2000;
346             case TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_LTE_CA ->
347                     AccessNetworkType.EUTRAN;
348             case TelephonyManager.NETWORK_TYPE_IWLAN -> AccessNetworkType.IWLAN;
349             case TelephonyManager.NETWORK_TYPE_NR -> AccessNetworkType.NGRAN;
350             default -> AccessNetworkType.UNKNOWN;
351         };
352     }
353 
354     /**
355      * Convert the elapsed time to the current time with readable time format.
356      *
357      * @param elapsedTime The elapsed time retrieved from {@link SystemClock#elapsedRealtime()}.
358      * @return The string format time.
359      */
360     @NonNull
361     public static String elapsedTimeToString(@ElapsedRealtimeLong long elapsedTime) {
362         return (elapsedTime != 0) ? systemTimeToString(System.currentTimeMillis()
363                 - SystemClock.elapsedRealtime() + elapsedTime) : "never";
364     }
365 
366     /**
367      * Convert the system time to the human readable format.
368      *
369      * @param systemTime The system time retrieved from {@link System#currentTimeMillis()}.
370      * @return The string format time.
371      */
372     @NonNull
373     public static String systemTimeToString(@CurrentTimeMillisLong long systemTime) {
374         return (systemTime != 0) ? TIME_FORMAT.format(systemTime) : "never";
375     }
376 
377     /**
378      * Convert the IMS feature to string.
379      *
380      * @param imsFeature IMS feature.
381      * @return IMS feature in string format.
382      */
383     @NonNull
384     public static String imsFeatureToString(@ImsFeature.FeatureType int imsFeature) {
385         return switch (imsFeature) {
386             case ImsFeature.FEATURE_MMTEL -> "MMTEL";
387             case ImsFeature.FEATURE_RCS -> "RCS";
388             default -> {
389                 loge("Unknown IMS feature(" + imsFeature + ")");
390                 yield "Unknown(" + imsFeature + ")";
391             }
392         };
393     }
394 
395     /**
396      * Group the network requests into several list that contains the same network capabilities.
397      *
398      * @param networkRequestList The provided network requests.
399      * @param featureFlags The feature flag.
400      *
401      * @return The network requests after grouping.
402      */
403     @NonNull
404     public static List<NetworkRequestList> getGroupedNetworkRequestList(
405             @NonNull NetworkRequestList networkRequestList, @NonNull FeatureFlags featureFlags) {
406         List<NetworkRequestList> requests = new ArrayList<>();
407         record NetworkCapabilitiesKey(Set<Integer> caps, Set<Integer> enterpriseIds,
408                                       Set<Integer> transportTypes) { }
409 
410         // Key is the combination of capabilities, enterprise ids, and transport types.
411         Map<NetworkCapabilitiesKey, NetworkRequestList> requestsMap = new ArrayMap<>();
412         for (TelephonyNetworkRequest networkRequest : networkRequestList) {
413             requestsMap.computeIfAbsent(new NetworkCapabilitiesKey(
414                             Arrays.stream(networkRequest.getCapabilities())
415                                     .boxed().collect(Collectors.toSet()),
416                             Arrays.stream(networkRequest.getNativeNetworkRequest()
417                                             .getEnterpriseIds())
418                                     .boxed().collect(Collectors.toSet()),
419                             Arrays.stream(networkRequest.getTransportTypes())
420                                     .boxed().collect(Collectors.toSet())
421                             ),
422                     v -> new NetworkRequestList()).add(networkRequest);
423         }
424         requests.addAll(requestsMap.values());
425         // Sort the requests so the network request list with higher priority will be at the front.
426         return requests.stream()
427                 .sorted((list1, list2) -> Integer.compare(
428                         list2.get(0).getPriority(), list1.get(0).getPriority()))
429                 .collect(Collectors.toList());
430     }
431 
432     /**
433      * Get the target transport from source transport. This is only used for handover between
434      * IWLAN and cellular scenario.
435      *
436      * @param sourceTransport The source transport.
437      * @return The target transport.
438      */
439     @TransportType
440     public static int getTargetTransport(@TransportType int sourceTransport) {
441         return sourceTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
442                 ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
443                 : AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
444     }
445 
446     /**
447      * Convert link status to string.
448      *
449      * @param linkStatus The link status.
450      * @return The link status in string format.
451      */
452     @NonNull
453     public static String linkStatusToString(@LinkStatus int linkStatus) {
454         return switch (linkStatus) {
455             case DataCallResponse.LINK_STATUS_UNKNOWN -> "UNKNOWN";
456             case DataCallResponse.LINK_STATUS_INACTIVE -> "INACTIVE";
457             case DataCallResponse.LINK_STATUS_ACTIVE -> "ACTIVE";
458             case DataCallResponse.LINK_STATUS_DORMANT -> "DORMANT";
459             default -> {
460                 loge("Unknown link status(" + linkStatus + ")");
461                 yield "UNKNOWN(" + linkStatus + ")";
462             }
463         };
464     }
465 
466     /**
467      * Check if access network type is valid.
468      *
469      * @param accessNetworkType The access network type to check.
470      * @return {@code true} if the access network type is valid.
471      */
472     public static boolean isValidAccessNetwork(@RadioAccessNetworkType int accessNetworkType) {
473         return switch (accessNetworkType) {
474             case AccessNetworkType.GERAN, AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN,
475                     AccessNetworkType.CDMA2000, AccessNetworkType.IWLAN, AccessNetworkType.NGRAN ->
476                     true;
477             default -> false;
478         };
479     }
480 
481     /**
482      * Convert data activity to string.
483      *
484      * @param dataActivity The data activity.
485      * @return The data activity in string format.
486      */
487     @NonNull
488     public static String dataActivityToString(@DataActivityType int dataActivity) {
489         return switch (dataActivity) {
490             case TelephonyManager.DATA_ACTIVITY_NONE -> "NONE";
491             case TelephonyManager.DATA_ACTIVITY_IN -> "IN";
492             case TelephonyManager.DATA_ACTIVITY_OUT -> "OUT";
493             case TelephonyManager.DATA_ACTIVITY_INOUT -> "INOUT";
494             case TelephonyManager.DATA_ACTIVITY_DORMANT -> "DORMANT";
495             default -> {
496                 loge("Unknown data activity(" + dataActivity + ")");
497                 yield "UNKNOWN(" + dataActivity + ")";
498             }
499         };
500     }
501 
502     private static void loge(String msg) {
503         Rlog.e(TAG, msg);
504     }
505 }
506