• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.android.iwlan;
18 
19 import android.content.Context;
20 import android.os.PersistableBundle;
21 import android.support.annotation.IntDef;
22 import android.support.annotation.NonNull;
23 import android.telephony.CarrierConfigManager;
24 import android.telephony.SubscriptionManager;
25 
26 import androidx.annotation.VisibleForTesting;
27 
28 /** Class for handling IWLAN carrier configuration. */
29 public class IwlanCarrierConfig {
30     static final String PREFIX = "iwlan.";
31 
32     /**
33      * Key for setting the delay in seconds to release the IWLAN connection after a handover to
34      * WWAN. Refer to {@link #DEFAULT_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT} for the default
35      * value.
36      */
37     public static final String KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT =
38             PREFIX + "handover_to_wwan_release_delay_second_int";
39 
40     /**
41      * Key to exclude IKE N1_MODE_CAPABILITY Notify payload during emergency session setup without
42      * affecting normal sessions. See {@link #DEFAULT_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL}
43      * for the default value.
44      */
45     public static final String KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL =
46             PREFIX + "n1_mode_exclusion_for_emergency_session_bool";
47 
48     /**
49      * Key to decide whether N1 mode shall be enabled or disabled depending on 5G enabling status
50      * via the UI/UX. See {@link #DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL} for the default value.
51      */
52     public static final String KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL =
53             PREFIX + "update_n1_mode_on_ui_change_bool";
54 
55     /**
56      * Boolean indicating if distinct ePDG selection for emergency sessions is enabled. Refer to
57      * {@link #DEFAULT_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL} for the default value.
58      */
59     public static final String KEY_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL =
60             PREFIX + "distinct_epdg_for_emergency_allowed_bool";
61 
62     /**
63      * Key to control whether the UE includes the IKE DEVICE_IDENTITY Notify payload when receiving
64      * a request. See {@link #DEFAULT_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL} for the default value.
65      */
66     public static final String KEY_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL =
67             PREFIX + "ike_device_identity_supported_bool";
68 
69     /**
70      * Boolean indicating if reordering ike SA transforms enabled. Refer to {@link
71      * #DEFAULT_IKE_SA_TRANSFORMS_REORDER_BOOL} for the default value.
72      */
73     public static final String KEY_IKE_SA_TRANSFORMS_REORDER_BOOL =
74             PREFIX + "ike_sa_transforms_reorder_bool";
75 
76     /** Trigger network validation when making a call */
77     public static final int NETWORK_VALIDATION_EVENT_MAKING_CALL = 0;
78 
79     /** Trigger network validation when screen on */
80     public static final int NETWORK_VALIDATION_EVENT_SCREEN_ON = 1;
81 
82     /** Trigger network validation when no response on network */
83     public static final int NETWORK_VALIDATION_EVENT_NO_RESPONSE = 2;
84 
85     @IntDef({
86         NETWORK_VALIDATION_EVENT_MAKING_CALL,
87         NETWORK_VALIDATION_EVENT_SCREEN_ON,
88         NETWORK_VALIDATION_EVENT_NO_RESPONSE
89     })
90     public @interface NetworkValidationEvent {}
91 
92     /**
93      * Key to control which events should trigger IWLAN underlying network validation when specific
94      * event received, possible values in the int array:
95      *
96      * <ul>
97      *   <li>0: NETWORK_VALIDATION_EVENT_MAKING_CALL
98      *   <li>1: NETWORK_VALIDATION_EVENT_SCREEN_ON
99      *   <li>2: NETWORK_VALIDATION_EVENT_NO_RESPONSE
100      * </ul>
101      */
102     public static final String KEY_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY =
103             PREFIX + "underlying_network_validation_events_int_array";
104 
105     /**
106      * IWLAN error policy configs that determine the behavior when error happens during ePDG tunnel
107      * setup. Refer to {@link #DEFAULT_ERROR_POLICY_CONFIG_STRING} for the default value.
108      *
109      * <p>The Error Config is defined as an Array of APNs identified by "ApnName". Other than Apn
110      * names this can also have "*" value which represents that this can be used as a generic
111      * fallback when no other policy matches.
112      *
113      * <p>Each APN associated with "ApnName" has an array of "ErrorTypes". Where each element in
114      * "ErrorTypes" array defines the config for the Error. The element in "ErrorTypes" array has
115      * the following items:
116      *
117      * <ul>
118      *   <li>"ErrorType": The type of error in String. Possible error types are:
119      *       <ol>
120      *         <li>"IKE_PROTOCOL_ERROR_TYPE" refers to the Notify Error coming in Notify payload.
121      *             See https://tools.ietf.org/html/rfc4306#section-3.10.1 for global errors and
122      *             carrier specific requirements for other carrier specific error codes.
123      *         <li>"GENERIC_ERROR_TYPE" refers to the following IWLAN errors - "IO_EXCEPTION",
124      *             "TIMEOUT_EXCEPTION", "SERVER_SELECTION_FAILED" and "TUNNEL_TRANSFORM_FAILED".
125      *         <li>"*" represents that this policy is a generic fallback when no other policy
126      *             matches.
127      *       </ol>
128      *   <li>"ErrorDetails": Array of errors specifics for which the policy needs to be applied to.
129      *       Note: Array can be a mix of numbers, ranges and string formats. Following are the
130      *       currently supported formats of elements in the array:
131      *       <ol>
132      *         <li>Number or Code: "24" - Number specific to the error.
133      *         <li>Range: "9000-9050" - Range of specific errors.
134      *         <li>Any: "*" value represents that this can be applied to all ErrorDetails when there
135      *             is no specific match. This will be a single element array.
136      *         <li>String: String describing the specific error. Current allowed string values -
137      *             "IO_EXCEPTION", "TIMEOUT_EXCEPTION", "SERVER_SELECTION_FAILED" and
138      *             "TUNNEL_TRANSFORM_FAILED"
139      *       </ol>
140      *       <p>"IKE_PROTOCOL_EXCEPTION" ErrorType expects the "error_detail" to be defined only in
141      *       numbers or range of numbers. Examples: ["24"] or ["9000-9050"] or ["7", "14000-14050"]
142      *       <p>"GENERIC_ERROR_TYPE" or "*" ErrorType expects only the following to be in
143      *       "ErrorDetails" - "IO_EXCEPTION", "TIMEOUT_EXCEPTION", "SERVER_SELECTION_FAILED",
144      *       "TUNNEL_TRANSFORM_FAILED" and "*". Examples: ["IO_EXCEPTION", "TIMEOUT_EXCEPTION"] or
145      *       ["*"]
146      *   <li>"RetryArray": Array of retry times (in secs) represented in string format. Following
147      *       formats are currently supported:
148      *       <ol>
149      *         <li>["0","0", "0"] Retry immediately for maximum 3 times and then fail.
150      *         <li>[] Empty array means to fail whenever the error happens.
151      *         <li>["2", "4", "8"] Retry times are 2 secs, 4secs and 8 secs - fail after that.
152      *         <li>["5", "10", "15", "-1"] Here the "-1" represents infinite retires with the retry
153      *             time "15" the last retry number).
154      *         <li>["2+r15"] 2 seconds + random time below 15 seconds, fail after that.
155      *       </ol>
156      *       <p>When fails, by default throttle for 24 hours.
157      *   <li>"UnthrottlingEvents": Events for which the retry time can be unthrottled in string.
158      *       Possible unthrottling events are:
159      *       <ol>
160      *         <li>"WIFI_DISABLE_EVENT": Wifi on to off toggle.
161      *         <li>"APM_DISABLE_EVENT": APM on to off toggle.
162      *         <li>"APM_ENABLE_EVENT": APM off to on toggle.
163      *         <li>"WIFI_AP_CHANGED_EVENT": Wifi is connected to an AP with different SSID.
164      *         <li>"WIFI_CALLING_DISABLE_EVENT": Wifi calling button on to off toggle.
165      *       </ol>
166      *   <li>"NumAttemptsPerFqdn" Integer to specify th count of tunnel setup attempts IWLAN must
167      *       perform with the IP address(es) returned by a single FQDN, before moving on to the next
168      *       FQDN. It is an optional field.
169      *   <li>"HandoverAttemptCount": Integer to specify the number of handover request attempts
170      *       before using initial attach instead. It is an optional field.
171      *       <p>"HandoverAttemptCount" should not be defined in the config when "ErrorType" is
172      *       defined as any other error types except "IKE_PROTOCOL_ERROR_TYPE", including "*".
173      * </ul>
174      *
175      * <p>Note: When the value is "*" for any of "ApnName" or "ErrorType" or "ErrorDetails", it
176      * means that the config definition applies to rest of the errors for which the config is not
177      * defined. For example, if "ApnName" is "ims" and one of the "ErrorType" in it is defined as
178      * "*" - this policy will be applied to the error that doesn't fall into other error types
179      * defined under "ims".
180      */
181     public static final String KEY_ERROR_POLICY_CONFIG_STRING =
182             PREFIX + "key_error_policy_config_string";
183 
184     /**
185      * Default delay in seconds for releasing the IWLAN connection after a WWAN handover. This is
186      * the default value for {@link #KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT}.
187      */
188     public static final int DEFAULT_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT = 0;
189 
190     /**
191      * The default value for determining whether the IKE N1_MODE_CAPABILITY Notify payload is
192      * excluded during emergency session setup.
193      */
194     public static final boolean DEFAULT_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL = false;
195 
196     /**
197      * The default value for determining whether N1 mode shall be enabled or disabled depending on
198      * 5G enabling status via the UI/UX.
199      */
200     public static final boolean DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL = false;
201 
202     /** This is the default value for {@link #KEY_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL}. */
203     public static final boolean DEFAULT_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL = false;
204 
205     /**
206      * Default value indicating whether the UE includes the IKE DEVICE_IDENTITY Notify payload upon
207      * receiving a request. This is the default setting for {@link
208      * #KEY_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL}.
209      */
210     public static final boolean DEFAULT_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL = false;
211 
212     /** This is the default value for {@link #KEY_IKE_SA_TRANSFORMS_REORDER_BOOL}. */
213     public static final boolean DEFAULT_IKE_SA_TRANSFORMS_REORDER_BOOL = false;
214 
215     /**
216      * The default value of which events should trigger IWLAN underlying network validation. This is
217      * the default value for {@link #KEY_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY}
218      */
219     public static final int[] DEFAULT_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY = {};
220 
221     /**
222      * The default value for determining IWLAN's behavior when error happens during ePDG tunnel
223      * setup. This is the default value for {@link #KEY_ERROR_POLICY_CONFIG_STRING}.
224      */
225     public static final String DEFAULT_ERROR_POLICY_CONFIG_STRING =
226             """
227             [{
228             "ApnName": "*",
229             "ErrorTypes": [{
230                 "ErrorType": "*",
231                 "ErrorDetails": ["*"],
232                 "RetryArray": ["1","2","2","10","20","40","80","160",
233                                 "320","640","1280","1800","3600","-1"],
234                 "UnthrottlingEvents": ["APM_ENABLE_EVENT","APM_DISABLE_EVENT",
235                                         "WIFI_DISABLE_EVENT","WIFI_AP_CHANGED_EVENT"]},{
236                 "ErrorType": "GENERIC_ERROR_TYPE",
237                 "ErrorDetails": ["IO_EXCEPTION"],
238                 "RetryArray": ["0","0","0","30","60+r15","120","-1"],
239                 "UnthrottlingEvents": ["APM_ENABLE_EVENT","APM_DISABLE_EVENT",
240                                         "WIFI_DISABLE_EVENT","WIFI_AP_CHANGED_EVENT"]},{
241                 "ErrorType": "IKE_PROTOCOL_ERROR_TYPE",
242                 "ErrorDetails": ["*"],
243                 "RetryArray": ["5","10","10","20","40","80","160",
244                                 "320","640","1280","1800","3600","-1"],
245                 "UnthrottlingEvents": ["APM_ENABLE_EVENT","WIFI_DISABLE_EVENT",
246                                         "WIFI_CALLING_DISABLE_EVENT"]},{
247                 "ErrorType": "IKE_PROTOCOL_ERROR_TYPE",
248                 "ErrorDetails": ["36"],
249                 "RetryArray": ["0","0","0","10","20","40","80","160",
250                                 "320","640","1280","1800","3600","-1"],
251                 "UnthrottlingEvents": ["APM_ENABLE_EVENT","WIFI_DISABLE_EVENT",
252                                         "WIFI_CALLING_DISABLE_EVENT"],
253                 "HandoverAttemptCount": "3"}]
254             }]
255             """;
256 
257     private static final PersistableBundle sTestBundle = new PersistableBundle();
258 
259     private static PersistableBundle sHiddenBundle = new PersistableBundle();
260 
261     static {
262         sHiddenBundle = createHiddenDefaultConfig();
263     }
264 
265     /**
266      * Creates a hidden default configuration.
267      *
268      * @return a PersistableBundle containing the hidden default configuration
269      */
createHiddenDefaultConfig()270     private static @NonNull PersistableBundle createHiddenDefaultConfig() {
271         PersistableBundle bundle = new PersistableBundle();
272         bundle.putInt(
273                 KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT,
274                 DEFAULT_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT);
275         bundle.putBoolean(
276                 KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL,
277                 DEFAULT_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL);
278         bundle.putBoolean(
279                 KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL);
280         bundle.putBoolean(
281                 KEY_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL,
282                 DEFAULT_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL);
283         bundle.putBoolean(
284                 KEY_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL, DEFAULT_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL);
285         bundle.putBoolean(
286                 KEY_IKE_SA_TRANSFORMS_REORDER_BOOL, DEFAULT_IKE_SA_TRANSFORMS_REORDER_BOOL);
287         bundle.putIntArray(
288                 KEY_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY,
289                 DEFAULT_UNDERLYING_NETWORK_VALIDATION_EVENTS_INT_ARRAY);
290         bundle.putString(KEY_ERROR_POLICY_CONFIG_STRING, DEFAULT_ERROR_POLICY_CONFIG_STRING);
291         return bundle;
292     }
293 
getConfig(Context context, int slotId, String key)294     private static PersistableBundle getConfig(Context context, int slotId, String key) {
295         if (sTestBundle.containsKey(key)) {
296             return sTestBundle;
297         }
298 
299         CarrierConfigManager carrierConfigManager =
300                 context.getSystemService(CarrierConfigManager.class);
301         if (carrierConfigManager == null) {
302             return getDefaultConfig(key);
303         }
304 
305         int subId = IwlanHelper.getSubId(context, slotId);
306         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
307             return getDefaultConfig(key);
308         }
309 
310         try {
311             PersistableBundle bundle = carrierConfigManager.getConfigForSubId(subId, key);
312             return bundle.containsKey(key) ? bundle : getDefaultConfig(key);
313         } catch (IllegalStateException e) {
314             // Fall through to return default config
315         }
316 
317         return getDefaultConfig(key);
318     }
319 
getDefaultConfig(String key)320     private static PersistableBundle getDefaultConfig(String key) {
321         PersistableBundle bundle = CarrierConfigManager.getDefaultConfig();
322         if (bundle.containsKey(key)) {
323             return bundle;
324         }
325 
326         if (sHiddenBundle.containsKey(key)) {
327             return sHiddenBundle;
328         }
329 
330         throw new IllegalArgumentException("Default config not found for key: " + key);
331     }
332 
333     /**
334      * Returns whether CarrierConfig is loaded for the given slot ID.
335      *
336      * @param context the application context
337      * @param slotId the slot ID
338      * @return Returns {@code true} if the CarrierConfig for the given slot ID is loaded.
339      */
isCarrierConfigLoaded(Context context, int slotId)340     static boolean isCarrierConfigLoaded(Context context, int slotId) {
341         int subId = IwlanHelper.getSubId(context, slotId);
342 
343         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
344             // Fail to query subscription id, just return false.
345             return false;
346         }
347 
348         CarrierConfigManager carrierConfigManager =
349                 context.getSystemService(CarrierConfigManager.class);
350         PersistableBundle bundle;
351         try {
352             bundle =
353                     carrierConfigManager != null
354                             ? carrierConfigManager.getConfigForSubId(
355                                     subId, CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL)
356                             : new PersistableBundle();
357         } catch (Exception e) {
358             bundle = new PersistableBundle();
359         }
360 
361         return CarrierConfigManager.isConfigForIdentifiedCarrier(bundle);
362     }
363 
364     /**
365      * Gets a configuration int value for a given slot ID and key.
366      *
367      * @param context the application context
368      * @param slotId the slot ID
369      * @param key the configuration key
370      * @return the configuration int value
371      */
getConfigInt(Context context, int slotId, String key)372     public static int getConfigInt(Context context, int slotId, String key) {
373         return getConfig(context, slotId, key).getInt(key);
374     }
375 
376     /**
377      * Gets a configuration long value for a given slot ID and key.
378      *
379      * @param context the application context
380      * @param slotId the slot ID
381      * @param key the configuration key
382      * @return the configuration long value
383      */
getConfigLong(Context context, int slotId, String key)384     public static long getConfigLong(Context context, int slotId, String key) {
385         return getConfig(context, slotId, key).getLong(key);
386     }
387 
388     /**
389      * Gets a configuration double value for a given slot ID and key.
390      *
391      * @param context the application context
392      * @param slotId the slot ID
393      * @param key the configuration key
394      * @return the configuration double value
395      */
getConfigDouble(Context context, int slotId, String key)396     public static double getConfigDouble(Context context, int slotId, String key) {
397         return getConfig(context, slotId, key).getDouble(key);
398     }
399 
400     /**
401      * Gets a configuration boolean value for a given slot ID and key.
402      *
403      * @param context the application context
404      * @param slotId the slot ID
405      * @param key the configuration key
406      * @return the configuration boolean value
407      */
getConfigBoolean(Context context, int slotId, String key)408     public static boolean getConfigBoolean(Context context, int slotId, String key) {
409         return getConfig(context, slotId, key).getBoolean(key);
410     }
411 
412     /**
413      * Gets a configuration string value for a given slot ID and key.
414      *
415      * @param context the application context
416      * @param slotId the slot ID
417      * @param key the configuration key
418      * @return the configuration string value
419      */
getConfigString(Context context, int slotId, String key)420     public static String getConfigString(Context context, int slotId, String key) {
421         return getConfig(context, slotId, key).getString(key);
422     }
423 
424     /**
425      * Gets a configuration int[] value for a given slot ID and key.
426      *
427      * @param context the application context
428      * @param slotId the slot ID
429      * @param key the configuration key
430      * @return the configuration int[] value
431      */
getConfigIntArray(Context context, int slotId, String key)432     public static int[] getConfigIntArray(Context context, int slotId, String key) {
433         return getConfig(context, slotId, key).getIntArray(key);
434     }
435 
436     /**
437      * Gets a configuration long[] value for a given slot ID and key.
438      *
439      * @param context the application context
440      * @param slotId the slot ID
441      * @param key the configuration key
442      * @return the configuration long[] value
443      */
getConfigLongArray(Context context, int slotId, String key)444     public static long[] getConfigLongArray(Context context, int slotId, String key) {
445         return getConfig(context, slotId, key).getLongArray(key);
446     }
447 
448     /**
449      * Gets a configuration double[] value for a given slot ID and key.
450      *
451      * @param context the application context
452      * @param slotId the slot ID
453      * @param key the configuration key
454      * @return the configuration double[] value
455      */
getConfigDoubleArray(Context context, int slotId, String key)456     public static double[] getConfigDoubleArray(Context context, int slotId, String key) {
457         return getConfig(context, slotId, key).getDoubleArray(key);
458     }
459 
460     /**
461      * Gets a configuration boolean[] value for a given slot ID and key.
462      *
463      * @param context the application context
464      * @param slotId the slot ID
465      * @param key the configuration key
466      * @return the configuration boolean[] value
467      */
getConfigBooleanArray(Context context, int slotId, String key)468     public static boolean[] getConfigBooleanArray(Context context, int slotId, String key) {
469         return getConfig(context, slotId, key).getBooleanArray(key);
470     }
471 
472     /**
473      * Gets a configuration string[] value for a given slot ID and key.
474      *
475      * @param context the application context
476      * @param slotId the slot ID
477      * @param key the configuration key
478      * @return the configuration string[] value
479      */
getConfigStringArray(Context context, int slotId, String key)480     public static String[] getConfigStringArray(Context context, int slotId, String key) {
481         return getConfig(context, slotId, key).getStringArray(key);
482     }
483 
484     /**
485      * Gets the default configuration int value for a given key.
486      *
487      * @param key the configuration key
488      * @return the default configuration int value
489      * @throws IllegalArgumentException if the default configuration is null for the given key
490      */
getDefaultConfigInt(String key)491     public static int getDefaultConfigInt(String key) {
492         return getDefaultConfig(key).getInt(key);
493     }
494 
495     /**
496      * Gets the default configuration long value for a given key.
497      *
498      * @param key the configuration key
499      * @return the default configuration long value
500      * @throws IllegalArgumentException if the default configuration is null for the given key
501      */
getDefaultConfigLong(String key)502     public static long getDefaultConfigLong(String key) {
503         return getDefaultConfig(key).getLong(key);
504     }
505 
506     /**
507      * Gets the default configuration double value for a given key.
508      *
509      * @param key the configuration key
510      * @return the default configuration double value
511      * @throws IllegalArgumentException if the default configuration is null for the given key
512      */
getDefaultConfigDouble(String key)513     public static double getDefaultConfigDouble(String key) {
514         return getDefaultConfig(key).getDouble(key);
515     }
516 
517     /**
518      * Gets the default configuration string value for a given key.
519      *
520      * @param key the configuration key
521      * @return the default configuration string value
522      * @throws IllegalArgumentException if the default configuration is null for the given key
523      */
getDefaultConfigString(String key)524     public static String getDefaultConfigString(String key) {
525         return getDefaultConfig(key).getString(key);
526     }
527 
528     /**
529      * Gets the default configuration boolean value for a given key.
530      *
531      * @param key the configuration key
532      * @return the default configuration boolean value
533      * @throws IllegalArgumentException if the default configuration is null for the given key
534      */
getDefaultConfigBoolean(String key)535     public static boolean getDefaultConfigBoolean(String key) {
536         return getDefaultConfig(key).getBoolean(key);
537     }
538 
539     /**
540      * Gets the default configuration int[] value for a given key.
541      *
542      * @param key the configuration key
543      * @return the default configuration int[] value
544      * @throws IllegalArgumentException if the default configuration is null for the given key
545      */
getDefaultConfigIntArray(String key)546     public static int[] getDefaultConfigIntArray(String key) {
547         return getDefaultConfig(key).getIntArray(key);
548     }
549 
550     /**
551      * Gets the default configuration long value for a given key.
552      *
553      * @param key the configuration key
554      * @return the default configuration long value
555      * @throws IllegalArgumentException if the default configuration is null for the given key
556      */
getDefaultConfigLongArray(String key)557     public static long[] getDefaultConfigLongArray(String key) {
558         return getDefaultConfig(key).getLongArray(key);
559     }
560 
561     /**
562      * Gets the default configuration double[] value for a given key.
563      *
564      * @param key the configuration key
565      * @return the default configuration double[] value
566      * @throws IllegalArgumentException if the default configuration is null for the given key
567      */
getDefaultConfigDoubleArray(String key)568     public static double[] getDefaultConfigDoubleArray(String key) {
569         return getDefaultConfig(key).getDoubleArray(key);
570     }
571 
572     /**
573      * Gets the default configuration string[] value for a given key.
574      *
575      * @param key the configuration key
576      * @return the default configuration string[] value
577      * @throws IllegalArgumentException if the default configuration is null for the given key
578      */
getDefaultConfigStringArray(String key)579     public static String[] getDefaultConfigStringArray(String key) {
580         return getDefaultConfig(key).getStringArray(key);
581     }
582 
583     /**
584      * Gets the default configuration boolean[] value for a given key.
585      *
586      * @param key the configuration key
587      * @return the default configuration boolean[] value
588      * @throws IllegalArgumentException if the default configuration is null for the given key
589      */
getDefaultConfigBooleanArray(String key)590     public static boolean[] getDefaultConfigBooleanArray(String key) {
591         return getDefaultConfig(key).getBooleanArray(key);
592     }
593 
594     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigBundle(PersistableBundle bundle)595     public static void putTestConfigBundle(PersistableBundle bundle) {
596         sTestBundle.putAll(bundle);
597     }
598 
599     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigInt(@onNull String key, int value)600     public static void putTestConfigInt(@NonNull String key, int value) {
601         sTestBundle.putInt(key, value);
602     }
603 
604     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigLong(@onNull String key, long value)605     public static void putTestConfigLong(@NonNull String key, long value) {
606         sTestBundle.putLong(key, value);
607     }
608 
609     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigDouble(@onNull String key, double value)610     public static void putTestConfigDouble(@NonNull String key, double value) {
611         sTestBundle.putDouble(key, value);
612     }
613 
614     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigBoolean(@onNull String key, boolean value)615     public static void putTestConfigBoolean(@NonNull String key, boolean value) {
616         sTestBundle.putBoolean(key, value);
617     }
618 
619     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigString(@onNull String key, String value)620     public static void putTestConfigString(@NonNull String key, String value) {
621         sTestBundle.putString(key, value);
622     }
623 
624     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigIntArray(@onNull String key, @NonNull int[] value)625     public static void putTestConfigIntArray(@NonNull String key, @NonNull int[] value) {
626         sTestBundle.putIntArray(key, value);
627     }
628 
629     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigLongArray(@onNull String key, @NonNull long[] value)630     public static void putTestConfigLongArray(@NonNull String key, @NonNull long[] value) {
631         sTestBundle.putLongArray(key, value);
632     }
633 
634     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigDoubleArray(@onNull String key, @NonNull double[] value)635     public static void putTestConfigDoubleArray(@NonNull String key, @NonNull double[] value) {
636         sTestBundle.putDoubleArray(key, value);
637     }
638 
639     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigBooleanArray(@onNull String key, @NonNull boolean[] value)640     public static void putTestConfigBooleanArray(@NonNull String key, @NonNull boolean[] value) {
641         sTestBundle.putBooleanArray(key, value);
642     }
643 
644     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
putTestConfigStringArray(@onNull String key, @NonNull String[] value)645     public static void putTestConfigStringArray(@NonNull String key, @NonNull String[] value) {
646         sTestBundle.putStringArray(key, value);
647     }
648 
649     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
resetTestConfig()650     public static void resetTestConfig() {
651         sTestBundle.clear();
652     }
653 
getUnderlyingNetworkValidationEventString( @wlanCarrierConfig.NetworkValidationEvent int event)654     public static String getUnderlyingNetworkValidationEventString(
655             @IwlanCarrierConfig.NetworkValidationEvent int event) {
656         return switch (event) {
657             case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_MAKING_CALL -> "MAKING_CALL";
658             case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_SCREEN_ON -> "SCREEN_ON";
659             case IwlanCarrierConfig.NETWORK_VALIDATION_EVENT_NO_RESPONSE -> "NO_RESPONSE";
660             default -> "UNKNOWN";
661         };
662     }
663 }
664