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.AccessNetworkConstants.TRANSPORT_TYPE_WLAN; 20 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 21 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_ECNO; 22 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP; 23 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP; 24 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ; 25 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI; 26 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR; 27 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP; 28 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ; 29 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR; 30 import static android.telephony.SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_UNKNOWN; 31 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; 32 33 import static com.android.telephony.qns.QnsConstants.FALLBACK_REASON_INVALID; 34 import static com.android.telephony.qns.QnsConstants.MAX_COUNT_INVALID; 35 import static com.android.telephony.qns.wfc.WfcCarrierConfigManager.KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT; 36 37 import android.annotation.IntDef; 38 import android.annotation.NonNull; 39 import android.content.Context; 40 import android.net.NetworkCapabilities; 41 import android.os.Handler; 42 import android.os.HandlerThread; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.PersistableBundle; 46 import android.telephony.AccessNetworkConstants; 47 import android.telephony.Annotation.NetCapability; 48 import android.telephony.CarrierConfigManager; 49 import android.telephony.SignalThresholdInfo; 50 import android.telephony.SubscriptionManager; 51 import android.telephony.TelephonyManager; 52 import android.telephony.ims.ImsMmTelManager; 53 import android.telephony.ims.ProvisioningManager; 54 import android.text.TextUtils; 55 import android.util.ArraySet; 56 import android.util.Log; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 60 import java.lang.annotation.Retention; 61 import java.lang.annotation.RetentionPolicy; 62 import java.util.ArrayList; 63 import java.util.Arrays; 64 import java.util.Collections; 65 import java.util.HashSet; 66 import java.util.List; 67 import java.util.Locale; 68 import java.util.Map; 69 import java.util.Set; 70 import java.util.stream.Collectors; 71 72 /** 73 * This class supports loading Ansp(Access Network Selection Policy , Thresholds , Handover Polices 74 * & Other Supporting Carrier configurations , to support ANE to decide on the HO decision 75 * management & listing related Access Network to pass to Telephony 76 */ 77 class QnsCarrierConfigManager { 78 /** 79 * Boolean indicating the WFC services in QNS Side is enabled, when airplane mode is On 80 * 81 * <p>{@code true}: QNS is enabled for WFC services in airplane mode on. {@code false}: QNS is 82 * disabled for WFC services in airplane mode on. The default value for this key is {@code true} 83 */ 84 static final String KEY_QNS_SUPPORT_WFC_DURING_AIRPLANE_MODE_BOOL = 85 "qns.support_wfc_during_airplane_mode_bool"; 86 87 /** 88 * Boolean indicating if in-call handover decision from WLAN to WWAN should consider VoPS 89 * status. 90 * 91 * <p>{@code true}: In-call handover decision from WLAN to WWAN won't consider VoPS status, for 92 * example, UE can perform handover from WLAN to LTE even if LTE network does not support VoPS. 93 * {@code false}: In-call handover decision from WLAN to WWAN will consider VoPS status, for 94 * example, UE should not perform handover from WLAN to LTE if LTE network does not support 95 * VoPS. 96 * The default value for this key is {@code false} 97 */ 98 static final String KEY_IN_CALL_HO_DECISION_WLAN_TO_WWAN_WITHOUT_VOPS_CONDITION_BOOL = 99 "qns.in_call_ho_decision_wlan_to_wwan_without_vops_condition_bool"; 100 101 /** 102 * Boolean indicating Iwlan TransportType priority is enabled , when VOPS(Voice Over PS Session) 103 * flag from NW is false . 104 * 105 * <p>{@code true}: Iwlan TransportType selection priority is enabled, when VOPS(Voice Over PS 106 * Session) is false. {@code false}: Iwlan TransportType selection priority is disabled, when 107 * VOPS (Voice Over PS Session) is false. The default value for this key is {@code true} 108 */ 109 static final String KEY_QNS_VOPS_NOTAVAILABLE_PRIORITY_IWLAN_BOOL = 110 "qns.support_vops_notavailable_priority_iwlan_bool"; 111 112 /** 113 * Boolean indicating when disabled , supporting of Guard Timer applied to both TransportType 114 * WWAN (Cellular) & WLAN ( Wifi) 115 * 116 * <p>{@code false}: Whe Disabled , Guard timer (To avoid Ping Pong) is executed for both the 117 * direction ( ie Cellular to Wifi & Wifi to Cellular) {@code true}: when enabled , Guard timer 118 * (To avoid Ping Pong) is executed only based on the preference set. The default value for this 119 * key is {@code false} 120 */ 121 static final String KEY_QNS_HO_GUARDING_BY_PREFERENCE_BOOL = 122 "qns.ho_guarding_by_preference_bool"; 123 /** 124 * Boolean indicating the Service Barring check is disabled, when making HO decision from 125 * transport type WWAN (Cellular) to Transport type WLAN Wifi 126 * 127 * <p>{@code false}: Service Barring check is disabled , when making HO decision from transport 128 * type WWAN (Cellular) to Transport type WLAN Wifi {@code true}: Service Barring check is 129 * enabled , when making HO decision from transport type WWAN (Cellular) to Transport type WLAN 130 * Wifi The default value for this key is {@code false} 131 */ 132 static final String KEY_QNS_SUPPORT_SERVICE_BARRING_CHECK_BOOL = 133 "qns.support_service_barring_check_bool"; 134 135 /** 136 * Boolean indicating the transport type selection without Signal Strength is disabled, during 137 * roaming condition 138 * 139 * <p>{@code false}: when disabled , transport type selection is based on RAT existence & signal 140 * quality during roaming.. {@code true}: when enabled , transport type selection is based on 141 * RAT availability during roaming. (not depends on Signal Strength) The default value for this 142 * key is {@code false} 143 */ 144 static final String KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL = 145 "qns.roam_transport_type_selection_without_signal_strength_bool"; 146 147 /** 148 * Boolean indicating the preference to select/continue call in current Transport Type is 149 * disabled. 150 * 151 * <p>{@code false}: When disabled , preference to select/continue call in current Transport 152 * Type is not allowed {@code true}: When enabled , preference to select/continue call in 153 * current Transport Type is allowed The default value for this key is {@code false} 154 */ 155 static final String KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL_BOOL = 156 "qns.prefer_current_transport_type_in_voice_call_bool"; 157 158 /** 159 * Boolean to override IMS Mode Preference from cellular preference. 160 * 161 * <p>{@code false}: When disabled , no ims override preference. {@code true}: When enabled , 162 * load ims mode preference instead of cellular mode preference at home network. The default 163 * value for this key is {@code false} 164 */ 165 static final String KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL = 166 "qns.override_cell_pref_to_ims_pref_home"; 167 168 /** 169 * Boolean indicating allowing video call over wifi is disabled , when cellular limited case 170 * meets.(ie no LTE home network is available, or if an LTE home network is available but VoPS 171 * is disabled or has 100% SSAC voice barring) 172 * 173 * <p>{@code false}: When disabled , preference to allow video call on meeting cellular limited 174 * case conditions over Wifi is not allowed. {@code true}: When enabled , preference to move 175 * video call on meeting cellular limited case conditions over Wifi is allowed. The default 176 * value for this key is {@code false} 177 */ 178 static final String KEY_QNS_ALLOW_VIDEO_OVER_IWLAN_WITH_CELLULAR_LIMITED_CASE_BOOL = 179 "qns.allow_video_over_iwlan_with_cellular_limited_case_bool"; 180 181 /** 182 * Boolean indicating cellular2WiFi-hysteresis Scenario rove out policies of WIth WIfi Bad 183 * criteria check with Guard TImer conditions is disabled. 184 * 185 * <p>{@code false}: When disabled , cellular2WiFi-hysteresis Scenario rove out policies during 186 * guard timer conditions(Running/Expired state) is not available {@code true}: When enabled , 187 * cellular2WiFi-hysteresis Scenario rove out policies during guard timer 188 * conditions(Running/Expired state) is available The default value for this key is {@code 189 * false} 190 */ 191 static final String KEY_QNS_ROVE_OUT_POLICY_WITH_WIFI_BAD_GUARDTIMER_CONDITIONS_BOOL = 192 "qns.rove_out_policy_with_wifi_bad_guardtimer_conditions_bool"; 193 194 /** 195 * Boolean indicating enabling of Wi-Fi call when in a call state idle with a cellular network 196 * that does not support ims pdn. 197 * 198 * <p>{@code false}: When disabled , There is no action to enable Wi-Fi Calling. {@code true}: 199 * When enabled , Enable Wi-Fi calling, if the call state is idle and the cellular network the 200 * UE is staying on does not allow ims pdn. The default value for this key is {@code false} 201 */ 202 static final String KEY_QNS_ALLOW_IMS_OVER_IWLAN_CELLULAR_LIMITED_CASE_BOOL = 203 "qns.allow_ims_over_iwlan_cellular_limited_case_bool"; 204 205 /** 206 * Boolean indicating if to block IWLAN when UE is in no WWAN coverage and the last stored 207 * country code is outside the home country. 208 * By default this value is {@code false}. 209 */ 210 static final String KEY_BLOCK_IWLAN_IN_INTERNATIONAL_ROAMING_WITHOUT_WWAN_BOOL = 211 "qns.block_iwlan_in_international_roaming_without_wwan_bool"; 212 213 /** 214 * Boolean indicating if to block IWLAN when UE is connected to IPv6 only WiFi AP. The setting 215 * may only apply on Android T. For Android U onwards, we may support a carrier config at IWLAN 216 * if we still encounter any issues for IPv6 WFC. By default this value is {@code true}. 217 */ 218 static final String KEY_BLOCK_IPV6_ONLY_WIFI_BOOL = "qns.block_ipv6_only_wifi_bool"; 219 220 /** 221 * Specifies the Rat Preference for the XCAP network capability. Boolean indicating adding the 222 * IMS Registration condition to the Wi-Fi Rove in condition. 223 * 224 * <ul> 225 * <li>{@code QnsConstants#RAT_PREFERENCE_DEFAULT}: Default, Follow the system preference. 226 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_ONLY}: If set , choose Wi-Fi always 227 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE}: If set , choose Wi-Fi when 228 * the Wi-Fi Calling is available.(when IMS is registered through the Wi-Fi) 229 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR}: If set , choose Wi-Fi when 230 * no cellular 231 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_HOME_IS_NOT_AVAILABLE}: If set , choose 232 * Wi-Fi when cellular is available at home network. 233 * </ul> 234 */ 235 static final String KEY_QNS_XCAP_RAT_PREFERENCE_INT = "qns.xcap_rat_preference_int"; 236 237 /** 238 * Specifies the Rat Preference for the SOS network capability. Boolean indicating adding the 239 * IMS Registration condition to the Wi-Fi Rove in condition. 240 * 241 * <ul> 242 * <li>{@code QnsConstants#RAT_PREFERENCE_DEFAULT}: Default, Follow the system preference. 243 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_ONLY}: If set , choose Wi-Fi always 244 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE}: If set , choose Wi-Fi when 245 * the Wi-Fi Calling is available.(when IMS is registered through the Wi-Fi) 246 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR}: If set , choose Wi-Fi when 247 * no cellular 248 * <li>{@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_HOME_IS_NOT_AVAILABLE}: If set , choose 249 * Wi-Fi when cellular is available at home network. 250 * </ul> 251 */ 252 static final String KEY_QNS_SOS_RAT_PREFERENCE_INT = "qns.sos_rat_preference_int"; 253 254 /** 255 * Specifies the Rat Preference for the MMS network capability. Boolean indicating adding the 256 * IMS Registration condition to the Wi-Fi Rove in condition. 257 * 258 * <p>{@code QnsConstants#RAT_PREFERENCE_DEFAULT}: Default value , Follow the system preference. 259 * {@code QnsConstants#RAT_PREFERENCE_WIFI_ONLY}: If set , choose Wi-Fi always {@code 260 * QnsConstants#RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE}: If set , choose Wi-Fi when the Wi-Fi 261 * Calling is available.(when IMS is registered through the Wi-Fi) {@code 262 * QnsConstants#RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR}: If set , choose Wi-Fi when no cellular 263 * {@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_HOME_IS_NOT_AVAILABLE}: If set , choose Wi-Fi 264 * when cellular is available at home network. The default value for this key is {@code 265 * QnsConstants#RAT_PREFERENCE_DEFAULT} 266 */ 267 static final String KEY_QNS_MMS_RAT_PREFERENCE_INT = "qns.mms_rat_preference_int"; 268 269 /** 270 * Specifies the Rat Preference for the CBS network capability. Boolean indicating adding the 271 * IMS Registration condition to the Wi-Fi Rove in condition. 272 * 273 * <p>{@code QnsConstants#RAT_PREFERENCE_DEFAULT}: Default value , Follow the system preference. 274 * {@code QnsConstants#RAT_PREFERENCE_WIFI_ONLY}: If set , choose Wi-Fi always {@code 275 * QnsConstants#RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE}: If set , choose Wi-Fi when the Wi-Fi 276 * Calling is available.(when IMS is registered through the Wi-Fi) {@code 277 * QnsConstants#RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR}: If set , choose Wi-Fi when no cellular 278 * {@code QnsConstants#RAT_PREFERENCE_WIFI_WHEN_HOME_IS_NOT_AVAILABLE}: If set , choose Wi-Fi 279 * when cellular is available at home network. The default value for this key is {@code 280 * QnsConstants#RAT_PREFERENCE_DEFAULT} 281 */ 282 static final String KEY_QNS_CBS_RAT_PREFERENCE_INT = "qns.cbs_rat_preference_int"; 283 284 /** 285 * Specifies the interval at which the Wifi Backhaul timer in milli seconds, for threshold Wifi 286 * rssi signal strength fluctuation in case, on meeting the criteria in Rove In Scenario (Moving 287 * to Cellular to Wifi) {@link QnsConstants}. The values are set as below: 288 * 289 * <ul> 290 * <li>0: {@link QnsConstants#DEFAULT_WIFI_BACKHAUL_TIMER} 291 * <li>1: {@link QnsConstants#KEY_DEFAULT_VALUE} 292 * </ul> 293 * 294 * &As per operator Requirements. 295 * 296 * <p>{@code QnsConstants#DEFAULT_WIFI_BACKHAUL_TIMER}: If set , specifies interval of 3secs 297 * running the backhaul check(To avoid Wifi Fluctuation) on meeting the criteria in Rove in case 298 * {@code QnsConstants#KEY_DEFAULT_VALUE}: If set , this feature to be disabled <As per Operator 299 * requirement configurable>: If this value set , specifies interval in milli seconds running 300 * the backhaul check. The default value for this key is {@link 301 * QnsConstants#DEFAULT_WIFI_BACKHAUL_TIMER} 302 */ 303 static final String KEY_QNS_WIFI_RSSI_THRESHOLDBACKHAUL_TIMER_MS_INT = 304 "qns.wifi_rssi_thresholdbackhaul_timer_int"; 305 306 /** 307 * Specifies the interval at which the Cellular Backhaul timer in milli seconds for cellular 308 * signal strengths fluctuation in case, on meeting the criteria in Rove out Scenario (Moving to 309 * Wifi from Cellular) The values are set as below: 310 * 311 * <ul> 312 * <li>0: {@link QnsConstants#KEY_DEFAULT_VALUE} 313 * </ul> 314 * 315 * &As per operator Requirements. 316 * 317 * <p>{@code QnsConstants#KEY_DEFAULT_VALUE}: If set , this feature to be disabled <As per 318 * Operator requirement configurable>: If this value set , specifies interval in milli seconds 319 * running the backhaul check over Cellular in Rove Out The default value for this key is {@link 320 * QnsConstants#KEY_DEFAULT_VALUE} 321 */ 322 static final String KEY_QNS_CELLULAR_SS_THRESHOLDBACKHAUL_TIMER_MS_INT = 323 "qns.cellular_ss_thresholdbackhaul_timer_int"; 324 325 /** 326 * Specifies the Transport type UE supports with QNS services for IMS network capability. {@link 327 * QnsConstants}. The values are set as below: 328 * 329 * <ul> 330 * <li>0: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 331 * <li>1: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN} 332 * <li>2: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH} 333 * </ul> 334 * 335 * {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN}: If set , Transport type UE supports is 336 * cellular for IMS network capability. {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN}: If 337 * this value set , Transport type UE supports is Wifi for IMS network capability. {@code 338 * QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH}: If this value set , Transport type UE supports is 339 * both Cellular & Wifi for IMS network capability The default value for this key is {@link 340 * QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH} 341 */ 342 static final String KEY_QNS_IMS_TRANSPORT_TYPE_INT = "qns.ims_transport_type_int"; 343 344 /** 345 * Specifies the Transport type UE supports with QNS services for SOS network capability. {@link 346 * QnsConstants}. The values are set as below: 347 * 348 * <ul> 349 * <li>0: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 350 * <li>1: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN} 351 * <li>2: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH} 352 * </ul> 353 * 354 * {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN}: If set , Transport type UE supports is 355 * cellular for SOS network capability. {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN}: If 356 * this value set , Transport type UE supports is Wifi for SOS network capability. {@code 357 * QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH}: If this value set , Transport type UE supports is 358 * both Cellular & Wifi for SOS network capability. The default value for this key is {@link 359 * QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 360 */ 361 static final String KEY_QNS_SOS_TRANSPORT_TYPE_INT = "qns.sos_transport_type_int"; 362 363 /** 364 * Specifies the Transport type UE supports with QNS services for MMS network capability. {@link 365 * QnsConstants}. The values are set as below: 366 * 367 * <ul> 368 * <li>0: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 369 * <li>1: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN} 370 * <li>2: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH} 371 * </ul> 372 * 373 * {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN}: If set , Transport type UE supports is 374 * cellular for MMS network capability. {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN}: If 375 * this value set , Transport type UE supports is Wifi for MMS network capability. {@code 376 * QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH}: If this value set , Transport type UE supports is 377 * both Cellular & Wifi for MMS network capability. The default value for this key is {@link 378 * QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 379 */ 380 static final String KEY_QNS_MMS_TRANSPORT_TYPE_INT = "qns.mms_transport_type_int"; 381 382 /** 383 * Specifies the Transport type UE supports with QNS services for CBS network capability. {@link 384 * QnsConstants}. The values are set as below: 385 * 386 * <ul> 387 * <li>0: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 388 * <li>1: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN} 389 * <li>2: {@link QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH} 390 * </ul> 391 * 392 * {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN}: If set , Transport type UE supports is 393 * cellular for CBS network capability. {@code QnsConstants#TRANSPORT_TYPE_ALLOWED_IWLAN}: If 394 * this value set , Transport type UE supports is Wifi for CBS network capability. {@code 395 * QnsConstants#TRANSPORT_TYPE_ALLOWED_BOTH}: If this value set , Transport type UE supports is 396 * both Cellular & Wifi for CBS network capability. The default value for this key is {@link 397 * QnsConstants#TRANSPORT_TYPE_ALLOWED_WWAN} 398 */ 399 static final String KEY_QNS_CBS_TRANSPORT_TYPE_INT = "qns.cbs_transport_type_int"; 400 401 /** 402 * For IMS PDN, specify a list of the hysteresis timer(millisecond) for handover from WLAN and 403 * WWAN to avoid ping-pong effect. 404 * 405 * <ul> 406 * <li>Index 0: The hysteresis timer for handover from WLAN and WWAN in idle state. 407 * <li>Index 1: The hysteresis timer for handover from WLAN and WWAN in voice call state. 408 * <li>Index 2: The hysteresis timer for handover from WLAN and WWAN in video call state. 409 * </ul> 410 * 411 * <p>The default values are {@link QnsConstants#KEY_DEFAULT_HYST_TIMER} 412 */ 413 static final String KEY_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY = 414 "qns.ims_wwan_hysteresis_timer_ms_int_array"; 415 416 /** 417 * For IMS PDN, specify a list of the hysteresis timer(millisecond) for handover from WWAN and 418 * WLAN to avoid ping-pong effect. 419 * 420 * <ul> 421 * <li>Index 0: The hysteresis timer for handover from WWAN and WLAN in idle state. 422 * <li>Index 1: The hysteresis timer for handover from WWAN and WLAN in voice call state. 423 * <li>Index 2: The hysteresis timer for handover from WWAN and WLAN in video call state. 424 * </ul> 425 * 426 * <p>The default values are {@link QnsConstants#KEY_DEFAULT_HYST_TIMER} 427 */ 428 static final String KEY_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY = 429 "qns.ims_wlan_hysteresis_timer_ms_int_array"; 430 431 /** 432 * Location(HOME/ROAM) of using handover hysteresis timer 433 * <li>0: {@link QnsConstants#COVERAGE_HOME} 434 * <li>1: {@link QnsConstants#COVERAGE_ROAM} 435 * <li>2: {@link QnsConstants#COVERAGE_BOTH} The default value for this key is {@link 436 * QnsConstants#COVERAGE_BOTH} 437 */ 438 static final String KEY_QNS_IMS_NETWORK_ENABLE_HO_HYSTERESIS_TIMER_INT = 439 "qns.ims_network_enable_hysteresis_timer_int"; 440 441 /** 442 * For MMS, XCAP and CBS PDNs, specify a list of the hysteresis timer(millisecond) for handover 443 * from WLAN and WWAN to avoid ping-pong effect. 444 * 445 * <ul> 446 * <li>Index 0: The hysteresis timer for handover from WLAN to WWAN in idle state. 447 * <li>Index 1: The hysteresis timer for handover from WLAN to WWAN in call state. 448 * </ul> 449 * 450 * <p>The default values are {@link QnsConstants#KEY_DEFAULT_VALUE} 451 */ 452 static final String KEY_NON_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY = 453 "qns.non_ims_wwan_hysteresis_timer_ms_int_array"; 454 455 /** 456 * For MMS, XCAP and CBS PDNs, specify a list of the hysteresis timer(millisecond) for handover 457 * from WWAN and WLAN to avoid ping-pong effect. 458 * 459 * <ul> 460 * <li>Index 0: The hysteresis timer for handover from WWAN and WLAN in idle state. 461 * <li>Index 1: The hysteresis timer for handover from WWAN and WLAN in call state. 462 * </ul> 463 * 464 * <p>The default values are {@link QnsConstants#KEY_DEFAULT_VALUE} 465 */ 466 static final String KEY_NON_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY = 467 "qns.non_ims_wlan_hysteresis_timer_ms_int_array"; 468 469 /** 470 * This item is the minimum handover guarding timer value when there is no guarding time for 471 * handover. 472 * Note: 473 * If this value is set to less than or equal to 0, minimum guarding action is disabled. 474 * if this value is set to greater than or equal to 475 * {@code QnsConstants#CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT}, 476 * {@code QnsConstants#CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT} value is set. 477 * If no value set at asset or paris , QnsConstants#CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER 478 * value at code is set. 479 * 480 * <p>{@code QnsConstants#CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER} : default value of timer. 481 * {@code QnsConstants#CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT} : maximum allowable 482 * value. 483 */ 484 static final String KEY_MINIMUM_HANDOVER_GUARDING_TIMER_MS_INT = 485 "qns.minimum_handover_guarding_timer_ms_int"; 486 487 /** 488 * This indicates time duration for packet loss rate sustained. 489 * 490 * <p/> The default value for this key is {@code 491 * QnsConstants#KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS} 492 */ 493 static final String KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT = 494 "qns.media_threshold_rtp_packet_loss_time_millis"; 495 496 /** 497 * Specify a list of the waiting time(millisecond) for the preferred transport type when power 498 * up. 499 * 500 * <ul> 501 * <li>Index 0: The waiting time for WWAN in cellular preferred mode. 502 * <li>Index 1: The waiting time for WLAN in WiFi preferred mode. 503 * </ul> 504 * 505 * <p>The default values are all {@link QnsConstants#KEY_DEFAULT_VALUE} 506 * 507 * <p>For example, if set 45000ms in the index 0 of this list, WLAN will be restricted 45000ms 508 * in cellular preferred mode when power up, and the timer will be canceled if IMS PDN is 509 * connected on WWAN within 45000ms. 510 */ 511 static final String KEY_WAITING_TIME_FOR_PREFERRED_TRANSPORT_WHEN_POWER_ON_INT_ARRAY = 512 "qns.waiting_time_for_preferred_transport_when_power_on_int_array"; 513 514 /** 515 * Specifies the number of count allowed IWLAN on HO to cellular during call due to fallback 516 * reason such as Wifi bad or RTP Low Quality Criteria 517 * 518 * <p>The Possible values are set as below: <rovein_count_allowed,rove_outfallback_reason 519 * 520 * <ul> 521 * <li><-1,-1></-1,-1>:{@link QnsConstants#MAX_COUNT_INVALID,QnsConstants#MAX_COUNT_INVALID} 522 * </ul> 523 * 524 * & As per operator Requirements (Ex: 3,1 or 1,2) 525 * 526 * <p>The default value for this key is {@link QnsConstants#MAX_COUNT_INVALID, 527 * QnsConstants#FALLBACK_REASON_INVALID} 528 */ 529 static final String KEY_QNS_IN_CALL_ROVEIN_ALLOWED_COUNT_AND_FALLBACK_REASON_INT_ARRAY = 530 "qns.in_call_rovein_allowed_and_fallback_reason_int_array"; 531 532 /** 533 * Specifies the number of count allowed IWLAN on HO to cellular during call due to fallback 534 * reason such as Wifi bad or RTP Low Quality Criteria 535 * 536 * <p>The Possible values are set as below: 537 * 538 * <ul> 539 * <li>Index 0: The waiting time for WLAN //If set to 0 , feature is disabled for WLAN-WWAN 540 * <li>Index 1: The waiting time for WWAN //If set to 0 , feature is disabled for WWAN-WLAN 541 * </ul> 542 * 543 * The default value for this key is {@link 544 * QnsConstants#KEY_DEFAULT_IWLAN_AVOID_TIME_LOW_RTP_QUALITY_MILLIS, 545 * QnsConstants#KEY_DEFAULT_VALUE} 546 */ 547 static final String KEY_QNS_HO_RESTRICT_TIME_WITH_LOW_RTP_QUALITY_MILLIS_INT_ARRAY = 548 "qns.ho_restrict_time_with_low_rtp_quality_int_array"; 549 550 /** 551 * Specify if choosing the transport type based on WFC preference mode when both WWAN and WLAN 552 * are not able to meet service requirements. 553 * 554 * <p>The possible values are set as below: 555 * 556 * <ul> 557 * <li>1: {@link ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED} 558 * <li>2: {@link ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED} 559 * </ul> 560 * 561 * {@code ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED}: Only apply the design when WFC 562 * preference mode is cellular preferred. Choose WWAN when cellular preferred and both WWAN and 563 * WLAN are in bad condition. {@code ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}: Only apply the 564 * design when WFC preference mode is WiFi preferred. Choose WLAN when WiFi preferred and both 565 * WWAN and WLAN are in bad condition. 566 * 567 * <p>If set to {ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED, 568 * ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}, the design will apply on both cellular and WiFi 569 * preference mode. 570 * 571 * <p>The default value for this key is empty. An empty array indicates staying on the current 572 * transport when both WWAN and WLAN are not able to meet service requirements. 573 */ 574 static final String KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY = 575 "qns.choose_wfc_preferred_transport_in_both_bad_condition_int_array"; 576 577 /** 578 * String indicating parameters for RTT(round trip time) check using ICMP PING on IWLAN. 579 * 580 * <p>We recommend to use a server on IWLAN path for RTT check. A server which is not reached 581 * via IWLAN connection may give inadequate result. 582 * 583 * <p>format:“<server_address>,<ping_count>,<intra_ping_interval>,<packet_size>,<rtt_criteria>, 584 * <rtt_check_Interval>,<hyst_fallback_timer>” For Ex: 585 * "epdg.epc.mnc001.mcc001.pub.3gppnetwork.org,5,100,32,100,1800000,600000" 586 * 587 * <p>The default value for this key is null indicating not enabled by default for round trip 588 * time check. 589 */ 590 static final String KEY_QNS_WLAN_RTT_BACKHAUL_CHECK_ON_ICMP_PING_STRING = 591 "qns.wlan_rtt_backhaul_check_on_icmp_ping_string"; 592 593 /** 594 * List of Array items indicating network capabilities with fallback support based on retry 595 * count or retry timer or either of them with fallback guard timer to be set 596 * 597 * <p><string-array name="qns.fallback_on_initial_connection_failure_string_array" num="2" <item 598 * value="<network_capability>:<retry_count>:<retry_timer>:<fallback_guard_timer> 599 * :<max_fallback_count>"/> Note: All Timer Values to be in millis Example: <item 600 * value="ims:3:60000:10000:2"/> <item value="mms:1:10000:60000:2"/> 601 * 602 * <p>The default value for this key is null indicating not enabled by default for fallback in 603 * case of initial connection failure 604 */ 605 static final String KEY_QNS_FALLBACK_ON_INITIAL_CONNECTION_FAILURE_STRING_ARRAY = 606 "qns.fallback_on_initial_connection_failure_string_array"; 607 608 /** 609 * List of Array items indicating the Access Network Allowed For IMS network capability. The 610 * values are set as below: "LTE" "NR" "3G" "2G" The default value for this key is {@Code 611 * "LTE","NR"} 612 */ 613 static final String KEY_IMS_CELLULAR_ALLOWED_RAT_STRING_ARRAY = 614 "qns.ims_cellular_allowed_rat_string_array"; 615 616 /** 617 * List of Array items indicating the Access Network Allowed For IMS network capability. The 618 * values are set as below: Format "<accessNetwork>:<meas_type>:<gap>" "eutran:rsrp:-2" 619 * "ngran:ssrsrp:2" Note: Similar format followed across different accessNetwork & Measurement 620 * Types. The default value for this key is "". 621 */ 622 static final String KEY_QNS_ROVEIN_THRESHOLD_GAP_WITH_GUARD_TIMER_STRING_ARRAY = 623 "qns.rove_in_threshold_gap_with_guard_timer_string_array"; 624 625 /** 626 * List of Array items indicating IMS unregistered cause & time(millis) for fallback (to WWAN). 627 * 628 * <p><string-array name="qns.fallback_wwan_ims_unregistration_reason_string_array" num="2"> 629 * <!-- fallback WWAN with ImsReason 321~378,1503 during 60sec at cellular prefer mode --> 630 * <item value="cause=321~378|1503, time=60000, preference=cell"/> 631 * <!-- fallback WWAN with ImsReason 240,243,323~350 during 90sec --> 632 * <item value="cause=240|243|323~350, time=90000"/> </string-array> 633 * 634 * <p>The default value for this key is "". 635 */ 636 static final String KEY_QNS_FALLBACK_WWAN_IMS_UNREGISTRATION_REASON_STRING_ARRAY = 637 "qns.fallback_wwan_ims_unregistration_reason_string_array"; 638 639 /** 640 * List of Array items indicating IMS HO registration fail cause & time(millis) for fallback (to 641 * WWAN). 642 * 643 * <p><string-array name="qns.fallback_wwan_ims_ho_reigster_fail_reason_string_array" num="2"> 644 * <!-- fallback WWAN with ImsReason 321~378,1503 during 60sec at cellular prefer mode --> 645 * <item value="cause=321~378|1503, time=60000, preference=cell"/> 646 * <!-- fallback WWAN with ImsReason 240,243,323~350 during 90sec --> 647 * <item value="cause=240|243|323~350, time=90000"/> </string-array> 648 * 649 * <p>The default value for this key is "". 650 */ 651 static final String KEY_QNS_FALLBACK_WWAN_IMS_HO_REGISTER_FAIL_REASON_STRING_ARRAY = 652 "qns.fallback_wwan_ims_ho_register_fail_reason_string_array"; 653 654 /** 655 * Specifies override the call precondition policy of AccessNetworkSelectionPolicy when the 656 * Sip Dialog Session is active. 657 * This Sip Dialog Session policy is applied when there is no calling in the subscription, and 658 * when the device is in a calling state, the calling policy is used first. 659 * 660 * <p> If the Sip Dialog Session is active, the AccessNetworkSelectionPolicy is applied as one 661 * of three policies: none, follow policy as voice call or as video call. 662 * <li>0: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_NONE} not Applied. The default value 663 * for this key. 664 * <li>1: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VOICE_CALL} apply voice call 665 * policy. 666 * <li>2: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VIDEO_CALL} apply video call 667 * policy. 668 */ 669 static final String KEY_SIP_DIALOG_SESSION_POLICY_INT = "qns.sip_dialog_session_policy_int"; 670 671 /** 672 * List of Array items indicating hysteresis db levels based on access network and measurement 673 * type , whose value to be used at api 674 * {@link SignalThresholdInfo#Builder().setHysteresisDb(int)} 675 * The values are set as Format "<accessNetwork>:<meas_type>:<hysteresisDb>" 676 * Ex: "eutran:rsrp:2","ngran:ssrsrp:1" 677 * 678 * The default value or if value set is less than zero, 679 * for this key is {@link QnsConstants#KEY_DEFAULT_VALUE} 680 * 681 */ 682 public static final String KEY_QNS_CELLULAR_SIGNAL_STRENGTH_HYSTERESIS_DB_STRING_ARRAY = 683 "qns.cellular_signal_strength_hysteresis_db_string_array"; 684 685 private static final Map<Integer, String> sAccessNetworkMap = Map.of( 686 AccessNetworkConstants.AccessNetworkType.EUTRAN, "eutran", 687 AccessNetworkConstants.AccessNetworkType.UTRAN, "utran", 688 AccessNetworkConstants.AccessNetworkType.NGRAN, "ngran", 689 AccessNetworkConstants.AccessNetworkType.GERAN, "geran", 690 AccessNetworkConstants.AccessNetworkType.IWLAN, "wifi" 691 ); 692 693 private static final Map<Integer, String> sMeasTypeMap = Map.of( 694 SIGNAL_MEASUREMENT_TYPE_RSRP, "rsrp", 695 SIGNAL_MEASUREMENT_TYPE_RSRQ, "rsrq", 696 SIGNAL_MEASUREMENT_TYPE_RSSNR, "rssnr", 697 SIGNAL_MEASUREMENT_TYPE_SSRSRP, "ssrsrp", 698 SIGNAL_MEASUREMENT_TYPE_SSRSRQ, "ssrsrq", 699 SIGNAL_MEASUREMENT_TYPE_SSSINR, "sssinr", 700 SIGNAL_MEASUREMENT_TYPE_RSCP, "rscp", 701 SIGNAL_MEASUREMENT_TYPE_RSSI, "rssi", 702 SIGNAL_MEASUREMENT_TYPE_ECNO, "ecno" 703 ); 704 705 private static final Map<Integer, String> sCallTypeMap = Map.of( 706 QnsConstants.CALL_TYPE_IDLE, "idle", 707 QnsConstants.CALL_TYPE_VOICE, "voice", 708 QnsConstants.CALL_TYPE_VIDEO, "video" 709 ); 710 711 private final String mLogTag; 712 private final int mSlotIndex; 713 private final Context mContext; 714 private boolean mIsConfigLoaded = false; 715 protected int mSubId; 716 protected int mCurrCarrierId; 717 private final QnsEventDispatcher mQnsEventDispatcher; 718 private final QnsCarrierAnspSupportConfig mAnspConfigMgr; 719 @VisibleForTesting final Handler mHandler; 720 721 private boolean mIsWfcInAirplaneModeOnSupport; 722 private boolean mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported; 723 private boolean mIsHoGuardOnPreferenceSupport; 724 private boolean mIsServiceBarringCheckSupport; 725 private boolean mIsVideoOverIWLANWithCellularCheckSupport; 726 private boolean mIsRoveOutWifiBadGuardTimerConditionsSupported; 727 private boolean mIsAllowImsOverIwlanCellularLimitedCase; 728 private boolean mIsBlockIwlanInInternationalRoamWithoutWwan; 729 private boolean mIsBlockIpv6OnlyWifi; 730 private boolean mIsVolteRoamingSupported; 731 private final boolean[] mAnspSupportConfigArray = new boolean[3]; 732 733 private int mWifiThresBackHaulTimer; 734 private int mCellularThresBackHaulTimer; 735 private int mQnsImsTransportType; 736 private int mQnsSosTransportType; 737 private int mQnsMmsTransportType; 738 private int[] mQnsXcapSupportedAccessNetworkTypes; 739 private int mQnsCbsTransportType; 740 private int mXcapRatPreference; 741 private int mSosRatPreference; 742 private int mMmsRatPreference; 743 private int mCbsRatPreference; 744 private int mNetworkEnableHysteresisTimer; 745 private int mMinimumHandoverGuardingTimer; 746 private int mVowifiRegistrationTimerForVowifiActivation; 747 private int mSipDialogSessionPolicy; 748 749 private int[] mWwanHysteresisTimer; 750 private int[] mWlanHysteresisTimer; 751 private int[] mNonImsWwanHysteresisTimer; 752 private int[] mNonImsWlanHysteresisTimer; 753 private int[] mRTPMetricsData = new int[4]; 754 private int[] mWaitingTimerForPreferredTransport; 755 private int[] mAllowMaxIwlanHoCountOnReason; 756 private int[] mHoRestrictTimeOnRtpQuality; 757 private int[] mIsMmtelCapabilityRequired; 758 private int[] mIsWfcPreferredTransportRequired; 759 760 private String mWlanRttBackhaulCheckConfigsOnPing; 761 private String[] mImsAllowedRats; 762 private String[] mRoveInGuardTimerConditionThresholdGaps; 763 private String[] mFallbackOnInitialConnectionFailure; 764 private String[] mAccessNetworkMeasurementHysteresisDb; 765 766 @NonNull 767 private final List<FallbackRule> mFallbackWwanRuleWithImsUnregistered = new ArrayList<>(); 768 769 @NonNull 770 private final List<FallbackRule> mFallbackWwanRuleWithImsHoRegisterFail = new ArrayList<>(); 771 772 /** Rules for handover between IWLAN and cellular network. */ 773 @NonNull private List<HandoverRule> mHandoverRuleList = new ArrayList<>(); 774 775 protected QnsRegistrantList mQnsCarrierConfigLoadedRegistrants = new QnsRegistrantList(); 776 protected QnsRegistrantList mQnsCarrierConfigChangedRegistrants = new QnsRegistrantList(); 777 778 protected QnsProvisioningListener.QnsProvisioningInfo mQnsProvisioningInfo = 779 new QnsProvisioningListener.QnsProvisioningInfo(); 780 setQnsProvisioningInfo(QnsProvisioningListener.QnsProvisioningInfo info)781 void setQnsProvisioningInfo(QnsProvisioningListener.QnsProvisioningInfo info) { 782 mQnsProvisioningInfo = info; 783 } 784 applyProvisioningInfo( QnsConfigArray thresholds, int accessNetwork, int measurementType, int callType)785 private QnsConfigArray applyProvisioningInfo( 786 QnsConfigArray thresholds, int accessNetwork, int measurementType, int callType) { 787 788 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_1) 789 && thresholds.mBad != QnsConfigArray.INVALID 790 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 791 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 792 int bad = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_1); 793 Log.d(mLogTag, "provisioning bad THLTE1 old:" + thresholds.mBad + " new:" + bad); 794 thresholds.mBad = bad; 795 } 796 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_2) 797 && thresholds.mWorst != QnsConfigArray.INVALID 798 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 799 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 800 int worst = 801 mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_2); 802 Log.d(mLogTag, "provisioning worst THLTE2 old:" + thresholds.mWorst + " new:" + worst); 803 thresholds.mWorst = worst; 804 } 805 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_3) 806 && thresholds.mGood != QnsConfigArray.INVALID 807 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 808 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 809 int good = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_3); 810 Log.d(mLogTag, "provisioning good THLTE3 old:" + thresholds.mGood + " new:" + good); 811 thresholds.mGood = good; 812 } 813 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_THRESHOLD_A) 814 && thresholds.mGood != QnsConfigArray.INVALID 815 && accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 816 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSSI) { 817 int good = 818 mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_A); 819 Log.d(mLogTag, "provisioning good VOWT_A old:" + thresholds.mGood + " new:" + good); 820 thresholds.mGood = good; 821 } 822 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_THRESHOLD_B) 823 && thresholds.mBad != QnsConfigArray.INVALID 824 && accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 825 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSSI) { 826 int bad = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_B); 827 Log.d(mLogTag, "provisioning bad VOWT_B old:" + thresholds.mBad + " new:" + bad); 828 thresholds.mBad = bad; 829 // TODO : make video threshold gap config, and move in getThreshold...() 830 if (getCarrierId() == 1839 && callType == QnsConstants.CALL_TYPE_VIDEO) { 831 thresholds.mBad = bad + 5; 832 } 833 } 834 835 return thresholds; 836 } 837 838 static class FallbackRule { 839 /** Key : IMS registration fail reason, value : fallback time in millis */ 840 final Set<Integer> mReasons; 841 842 final int mBackoffTimeMillis; 843 final int mPreferenceMode; 844 FallbackRule(Set<Integer> reasons, int backoffTimeMillis, int preferenceMode)845 FallbackRule(Set<Integer> reasons, int backoffTimeMillis, int preferenceMode) { 846 mReasons = reasons; 847 mBackoffTimeMillis = backoffTimeMillis; 848 mPreferenceMode = preferenceMode; 849 } 850 getFallBackTime(int reason)851 int getFallBackTime(int reason) { 852 if (mReasons.contains(reason)) { 853 return mBackoffTimeMillis; 854 } else { 855 return 0; 856 } 857 } 858 859 @Override toString()860 public String toString() { 861 StringBuilder builder = new StringBuilder(); 862 builder.append("FallbackRule time:").append(mBackoffTimeMillis); 863 if (mPreferenceMode == -1) { 864 builder.append(" "); 865 } else if (mPreferenceMode == QnsConstants.CELL_PREF) { 866 builder.append(" " + "CELL_PREF_MODE"); 867 } else if (mPreferenceMode == QnsConstants.WIFI_PREF) { 868 builder.append(" " + "WIFI_PREF_MODE"); 869 } 870 builder.append(" reasons:"); 871 for (Integer i : mReasons) { 872 builder.append(i).append(" "); 873 } 874 return builder.toString(); 875 } 876 } 877 878 static class HandoverRule { 879 @Retention(RetentionPolicy.SOURCE) 880 @IntDef( 881 prefix = {"RULE_TYPE_"}, 882 value = { 883 RULE_TYPE_ALLOWED, 884 RULE_TYPE_DISALLOWED, 885 }) 886 @interface HandoverRuleType {} 887 888 /** Indicating this rule is for allowing handover. */ 889 static final int RULE_TYPE_ALLOWED = 1; 890 891 /** Indicating this rule is for disallowing handover. */ 892 static final int RULE_TYPE_DISALLOWED = 2; 893 894 private static final String RULE_TAG_SOURCE_ACCESS_NETWORKS = "source"; 895 896 private static final String RULE_TAG_TARGET_ACCESS_NETWORKS = "target"; 897 898 private static final String RULE_TAG_TYPE = "type"; 899 900 private static final String RULE_TAG_CAPABILITIES = "capabilities"; 901 902 private static final String RULE_TAG_ROAMING = "roaming"; 903 904 /** Handover rule type. */ 905 @HandoverRuleType final int mHandoverRuleType; 906 907 /** The applicable source access networks for handover. */ 908 @NonNull @AccessNetworkConstants.RadioAccessNetworkType 909 final Set<Integer> mSourceAccessNetworks; 910 911 /** The applicable target access networks for handover. */ 912 @NonNull @AccessNetworkConstants.RadioAccessNetworkType 913 final Set<Integer> mTargetAccessNetworks; 914 915 /** 916 * The network capabilities to any of which this handover rule applies. If is empty, then 917 * capability is ignored as a rule matcher. 918 */ 919 @NonNull @NetCapability final Set<Integer> mNetworkCapabilities; 920 921 /** {@code true} indicates this policy is only applicable when the device is roaming. */ 922 final boolean mIsOnlyForRoaming; 923 924 /** 925 * Constructor 926 * 927 * @param ruleString The rule in string format. 928 * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY 929 */ HandoverRule(@onNull String ruleString)930 HandoverRule(@NonNull String ruleString) { 931 if (TextUtils.isEmpty(ruleString)) { 932 throw new IllegalArgumentException("illegal rule " + ruleString); 933 } 934 935 Set<Integer> source = null, target = null, capabilities = Collections.emptySet(); 936 int type = 0; 937 boolean roaming = false; 938 939 ruleString = ruleString.trim().toLowerCase(Locale.ROOT); 940 String[] expressions = ruleString.split("\\s*,\\s*"); 941 for (String expression : expressions) { 942 String[] tokens = expression.trim().split("\\s*=\\s*"); 943 if (tokens.length != 2) { 944 throw new IllegalArgumentException( 945 "illegal rule " + ruleString + ", tokens=" + Arrays.toString(tokens)); 946 } 947 String key = tokens[0].trim(); 948 String value = tokens[1].trim(); 949 try { 950 switch (key) { 951 case RULE_TAG_SOURCE_ACCESS_NETWORKS: 952 source = 953 Arrays.stream(value.split("\\s*\\|\\s*")) 954 .map(String::trim) 955 .map(QnsConstants::accessNetworkTypeFromString) 956 .collect(Collectors.toSet()); 957 break; 958 case RULE_TAG_TARGET_ACCESS_NETWORKS: 959 target = 960 Arrays.stream(value.split("\\s*\\|\\s*")) 961 .map(String::trim) 962 .map(QnsConstants::accessNetworkTypeFromString) 963 .collect(Collectors.toSet()); 964 break; 965 case RULE_TAG_TYPE: 966 if (value.toLowerCase(Locale.ROOT).equals("allowed")) { 967 type = RULE_TYPE_ALLOWED; 968 } else if (value.toLowerCase(Locale.ROOT).equals("disallowed")) { 969 type = RULE_TYPE_DISALLOWED; 970 } else { 971 throw new IllegalArgumentException("unexpected rule type " + value); 972 } 973 break; 974 case RULE_TAG_CAPABILITIES: 975 capabilities = QnsUtils.getNetworkCapabilitiesFromString(value); 976 break; 977 case RULE_TAG_ROAMING: 978 roaming = Boolean.parseBoolean(value); 979 break; 980 default: 981 throw new IllegalArgumentException("unexpected key " + key); 982 } 983 } catch (Exception e) { 984 e.printStackTrace(); 985 throw new IllegalArgumentException( 986 "illegal rule \"" + ruleString + "\", e=" + e); 987 } 988 } 989 990 if (source == null || target == null || source.isEmpty() || target.isEmpty()) { 991 throw new IllegalArgumentException( 992 "Need to specify both source and target. " + "\"" + ruleString + "\""); 993 } 994 995 if (source.contains(AccessNetworkConstants.AccessNetworkType.UNKNOWN) 996 && type != RULE_TYPE_DISALLOWED) { 997 throw new IllegalArgumentException("Unknown access network can be only specified in" 998 + " the disallowed rule. \"" + ruleString + "\""); 999 } 1000 1001 if (target.contains(AccessNetworkConstants.AccessNetworkType.UNKNOWN)) { 1002 throw new IllegalArgumentException( 1003 "Target access networks contains unknown. " + "\"" + ruleString + "\""); 1004 } 1005 1006 if (type == 0) { 1007 throw new IllegalArgumentException( 1008 "Rule type is not specified correctly. " + "\"" + ruleString + "\""); 1009 } 1010 1011 if (capabilities != null && capabilities.contains(-1)) { 1012 throw new IllegalArgumentException( 1013 "Network capabilities contains unknown. " + "\"" + ruleString + "\""); 1014 } 1015 1016 if (!source.contains(AccessNetworkConstants.AccessNetworkType.IWLAN) 1017 && !target.contains(AccessNetworkConstants.AccessNetworkType.IWLAN)) { 1018 throw new IllegalArgumentException( 1019 "IWLAN must be specified in either source or " 1020 + "target access networks.\"" 1021 + ruleString 1022 + "\""); 1023 } 1024 1025 mSourceAccessNetworks = source; 1026 mTargetAccessNetworks = target; 1027 this.mHandoverRuleType = type; 1028 mNetworkCapabilities = capabilities; 1029 mIsOnlyForRoaming = roaming; 1030 } 1031 1032 @Override toString()1033 public String toString() { 1034 return "[HandoverRule: type=" 1035 + (mHandoverRuleType == RULE_TYPE_ALLOWED ? "allowed" : "disallowed") 1036 + ", source=" 1037 + mSourceAccessNetworks.stream() 1038 .map(QnsConstants::accessNetworkTypeToString) 1039 .collect(Collectors.joining("|")) 1040 + ", target=" 1041 + mTargetAccessNetworks.stream() 1042 .map(QnsConstants::accessNetworkTypeToString) 1043 .collect(Collectors.joining("|")) 1044 + ", isRoaming=" 1045 + mIsOnlyForRoaming 1046 + ", capabilities=" 1047 + QnsUtils.networkCapabilitiesToString(mNetworkCapabilities) 1048 + "]"; 1049 } 1050 } 1051 1052 private class QnsCarrierConfigChangeHandler extends Handler { QnsCarrierConfigChangeHandler(Looper looper)1053 QnsCarrierConfigChangeHandler(Looper looper) { 1054 super(looper); 1055 } 1056 1057 @Override handleMessage(Message message)1058 public void handleMessage(Message message) { 1059 switch (message.what) { 1060 case QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED: 1061 Log.d(mLogTag, "Event received QNS_EVENT_CARRIER_CONFIG_CHANGED"); 1062 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1063 int newCarrierID = getCarrierId(); 1064 Log.d( 1065 mLogTag, 1066 "Carrier Id: current=" + mCurrCarrierId + ", new=" + newCarrierID); 1067 if (newCarrierID != 0 && newCarrierID != UNKNOWN_CARRIER_ID) { 1068 if (mCurrCarrierId != newCarrierID) { 1069 mCurrCarrierId = newCarrierID; 1070 loadQnsConfigurations(); 1071 mIsConfigLoaded = true; 1072 notifyLoadQnsConfigurationsCompleted(); 1073 } else { 1074 if (isQnsConfigChanged()) { 1075 Log.d(mLogTag, "Qns Carrier config updated found"); 1076 notifyQnsConfigurationsChanged(); 1077 } 1078 } 1079 } 1080 } 1081 break; 1082 default: 1083 break; 1084 } 1085 } 1086 } 1087 1088 /** 1089 * Constructor to Initial Slot and Context whose carrier config ID needs to be loaded along with 1090 * initialising the Action Intent on which Carrier Config ID to be loaded. 1091 */ QnsCarrierConfigManager(Context context, QnsEventDispatcher dispatcher, int slotIndex)1092 QnsCarrierConfigManager(Context context, QnsEventDispatcher dispatcher, int slotIndex) { 1093 mSlotIndex = slotIndex; 1094 mContext = context; 1095 mLogTag = 1096 QnsConstants.QNS_TAG 1097 + "_" 1098 + QnsCarrierConfigManager.class.getSimpleName() 1099 + "_" 1100 + mSlotIndex; 1101 mQnsEventDispatcher = dispatcher; 1102 mAnspConfigMgr = new QnsCarrierAnspSupportConfig(slotIndex); 1103 1104 HandlerThread handlerThread = new HandlerThread(mLogTag); 1105 handlerThread.start(); 1106 mHandler = 1107 new QnsCarrierConfigManager.QnsCarrierConfigChangeHandler( 1108 handlerThread.getLooper()); 1109 1110 List<Integer> events = new ArrayList<>(); 1111 events.add(QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED); 1112 mQnsEventDispatcher.registerEvent(events, mHandler); 1113 1114 // sending empty message when new object created; as actual event will not be received in 1115 // case QNS restarts. 1116 // This EVENT will not be processed in bootup case since carrier id will be invalid until 1117 // actual event received from QnsEventDispatcher. 1118 mHandler.sendEmptyMessage(QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED); 1119 1120 // To do : Update based on xml version Changes handling 1121 // To do : Operator Update on Threshold changes handling 1122 } 1123 1124 /** Below API clears the current Access Network selection Policies */ close()1125 void close() { 1126 if (mHandler != null) mQnsEventDispatcher.unregisterEvent(mHandler); 1127 } 1128 readFromCarrierConfigManager(Context context)1129 synchronized PersistableBundle readFromCarrierConfigManager(Context context) { 1130 PersistableBundle carrierConfigBundle; 1131 CarrierConfigManager carrierConfigManager = 1132 context.getSystemService(CarrierConfigManager.class); 1133 1134 if (carrierConfigManager == null) { 1135 throw new IllegalStateException("Carrier config manager is null."); 1136 } 1137 carrierConfigBundle = carrierConfigManager.getConfigForSubId(getSubId()); 1138 1139 return carrierConfigBundle; 1140 } 1141 readFromAssets(Context context)1142 synchronized PersistableBundle readFromAssets(Context context) { 1143 PersistableBundle assetBundle; 1144 1145 assetBundle = QnsUtils.readQnsDefaultConfigFromAssets(context, mCurrCarrierId); 1146 1147 if (assetBundle == null) { 1148 throw new IllegalStateException("Carrier config manager is null."); 1149 } 1150 1151 return assetBundle; 1152 } 1153 1154 /** Below API is used for Loading the carrier configurations based on Current Carrier ID */ loadQnsConfigurations()1155 void loadQnsConfigurations() { 1156 1157 PersistableBundle carrierConfigBundle = readFromCarrierConfigManager(mContext); 1158 Log.d(mLogTag, "CarrierConfig Bundle for Slot: " + mSlotIndex + carrierConfigBundle); 1159 1160 PersistableBundle assetConfigBundle = readFromAssets(mContext); 1161 Log.d(mLogTag, "AssetConfig Bundle for Slot: " + mSlotIndex + assetConfigBundle); 1162 1163 // load configurations supporting ANE 1164 loadQnsAneSupportConfigurations(carrierConfigBundle, assetConfigBundle); 1165 1166 // load qns Ansp (Access Network Selection Policy) carrier Support Configurations 1167 // for building Internal ANSP Policies 1168 loadAnspCarrierSupportConfigs(carrierConfigBundle, assetConfigBundle); 1169 1170 mAnspConfigMgr.loadQnsAnspSupportArray(carrierConfigBundle, assetConfigBundle); 1171 1172 // Load configs using Carrier Config Manager Keys 1173 loadDirectFromCarrierConfigManagerKey(carrierConfigBundle); 1174 1175 loadWfcConfigurations(carrierConfigBundle, assetConfigBundle); 1176 1177 loadMediaThreshold(carrierConfigBundle, assetConfigBundle); 1178 } 1179 1180 /** 1181 * Below API takes care of loading the configuration based on the carrier config Manager 1182 * available for given carrier config manager keys. 1183 */ loadDirectFromCarrierConfigManagerKey(PersistableBundle bundleCarrier)1184 void loadDirectFromCarrierConfigManagerKey(PersistableBundle bundleCarrier) { 1185 loadHandoverRules( 1186 bundleCarrier, null, CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY); 1187 loadCarrierConfig(bundleCarrier); 1188 } 1189 1190 /** 1191 * Below API takes care of validating the configs (Threshold & HO rules) Updates after loading 1192 * Qns configurations, for the current operator in use, in case of config update scenario 1193 * 1194 * @return : true/false 1195 */ isQnsConfigChanged()1196 synchronized boolean isQnsConfigChanged() { 1197 PersistableBundle carrierConfigBundle = readFromCarrierConfigManager(mContext); 1198 Log.d( 1199 mLogTag, 1200 "Check carrier config for Qns item changefor_slot: " 1201 + mSlotIndex 1202 + "_" 1203 + carrierConfigBundle); 1204 PersistableBundle assetConfigBundle = readFromAssets(mContext); 1205 Log.d( 1206 mLogTag, 1207 "Check Asset config for Qns item changefor_slot: " 1208 + mSlotIndex 1209 + "_" 1210 + assetConfigBundle); 1211 1212 boolean isThresholdConfigChanged = 1213 checkThresholdConfigChange(carrierConfigBundle, assetConfigBundle); 1214 boolean isHandoverRulesChanged = 1215 checkHandoverRuleConfigChange( 1216 carrierConfigBundle, 1217 null, 1218 CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY); 1219 Log.d( 1220 mLogTag, 1221 "Threshold config changed = " 1222 + isThresholdConfigChanged 1223 + ", IMS handover rule changed = " 1224 + isHandoverRulesChanged); 1225 1226 return (isThresholdConfigChanged || isHandoverRulesChanged); 1227 } 1228 1229 /** 1230 * Below API takes to check if current HO rules as any difference with existing HO rules Updated 1231 * based on Event Carrier config change event received after initial loading @Param 1232 * PersistableBundle : configBundle 1233 * 1234 * @return true/false 1235 */ checkHandoverRuleConfigChange( PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle, String key)1236 synchronized boolean checkHandoverRuleConfigChange( 1237 PersistableBundle carrierConfigBundle, 1238 PersistableBundle assetConfigBundle, 1239 String key) { 1240 List<HandoverRule> handoverUpdateRuleList = 1241 updateHandoverRules(carrierConfigBundle, assetConfigBundle, key); 1242 1243 Log.d(mLogTag, "New rule:" + handoverUpdateRuleList.toString()); 1244 Log.d(mLogTag, "Existing rule:" + mHandoverRuleList.toString()); 1245 1246 if (mHandoverRuleList.toString().equals(handoverUpdateRuleList.toString()) 1247 || handoverUpdateRuleList.isEmpty() 1248 || mHandoverRuleList.isEmpty()) { 1249 handoverUpdateRuleList.clear(); 1250 return false; 1251 } else { 1252 mHandoverRuleList = new ArrayList<>(handoverUpdateRuleList); 1253 Log.d(mLogTag, "New rule Updated:" + mHandoverRuleList); 1254 handoverUpdateRuleList.clear(); 1255 return true; 1256 } 1257 } 1258 1259 /** 1260 * Below API takes to check if ANSP threshold configs was Updated based on Event Carrier config 1261 * change event received after initial Qns configuration loading is completed 1262 */ checkThresholdConfigChange( PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle)1263 synchronized boolean checkThresholdConfigChange( 1264 PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle) { 1265 1266 return mAnspConfigMgr.checkQnsAnspConfigChange(carrierConfigBundle, assetConfigBundle); 1267 } 1268 1269 /** 1270 * Below API takes care of loading the configuration based on the Bundle data built based on 1271 * asset folder xml file . (Except reading Key item of threshold & ANSP 1272 */ loadQnsAneSupportConfigurations( PersistableBundle bundleCarrier, PersistableBundle bundleAsset)1273 void loadQnsAneSupportConfigurations( 1274 PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 1275 1276 mIsWfcInAirplaneModeOnSupport = 1277 getConfig( 1278 bundleCarrier, bundleAsset, KEY_QNS_SUPPORT_WFC_DURING_AIRPLANE_MODE_BOOL); 1279 mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported = 1280 getConfig( 1281 bundleCarrier, 1282 bundleAsset, 1283 KEY_IN_CALL_HO_DECISION_WLAN_TO_WWAN_WITHOUT_VOPS_CONDITION_BOOL); 1284 mIsHoGuardOnPreferenceSupport = 1285 getConfig(bundleCarrier, bundleAsset, KEY_QNS_HO_GUARDING_BY_PREFERENCE_BOOL); 1286 mIsServiceBarringCheckSupport = 1287 getConfig(bundleCarrier, bundleAsset, KEY_QNS_SUPPORT_SERVICE_BARRING_CHECK_BOOL); 1288 mIsVideoOverIWLANWithCellularCheckSupport = 1289 getConfig( 1290 bundleCarrier, 1291 bundleAsset, 1292 KEY_QNS_ALLOW_VIDEO_OVER_IWLAN_WITH_CELLULAR_LIMITED_CASE_BOOL); 1293 mIsRoveOutWifiBadGuardTimerConditionsSupported = 1294 getConfig( 1295 bundleCarrier, 1296 bundleAsset, 1297 KEY_QNS_ROVE_OUT_POLICY_WITH_WIFI_BAD_GUARDTIMER_CONDITIONS_BOOL); 1298 mIsAllowImsOverIwlanCellularLimitedCase = 1299 getConfig( 1300 bundleCarrier, 1301 bundleAsset, 1302 KEY_QNS_ALLOW_IMS_OVER_IWLAN_CELLULAR_LIMITED_CASE_BOOL); 1303 mIsBlockIwlanInInternationalRoamWithoutWwan = 1304 getConfig( 1305 bundleCarrier, 1306 bundleAsset, 1307 KEY_BLOCK_IWLAN_IN_INTERNATIONAL_ROAMING_WITHOUT_WWAN_BOOL); 1308 mIsBlockIpv6OnlyWifi = getConfig(bundleCarrier, bundleAsset, KEY_BLOCK_IPV6_ONLY_WIFI_BOOL); 1309 1310 mWifiThresBackHaulTimer = 1311 getConfig( 1312 bundleCarrier, 1313 bundleAsset, 1314 KEY_QNS_WIFI_RSSI_THRESHOLDBACKHAUL_TIMER_MS_INT); 1315 mCellularThresBackHaulTimer = 1316 getConfig( 1317 bundleCarrier, 1318 bundleAsset, 1319 KEY_QNS_CELLULAR_SS_THRESHOLDBACKHAUL_TIMER_MS_INT); 1320 mQnsImsTransportType = 1321 getConfig(bundleCarrier, bundleAsset, KEY_QNS_IMS_TRANSPORT_TYPE_INT); 1322 mQnsSosTransportType = 1323 getConfig(bundleCarrier, bundleAsset, KEY_QNS_SOS_TRANSPORT_TYPE_INT); 1324 mQnsMmsTransportType = 1325 getConfig(bundleCarrier, bundleAsset, KEY_QNS_MMS_TRANSPORT_TYPE_INT); 1326 mQnsXcapSupportedAccessNetworkTypes = 1327 getConfig( 1328 bundleCarrier, 1329 bundleAsset, 1330 CarrierConfigManager.ImsSs.KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY); 1331 mQnsCbsTransportType = 1332 getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_TRANSPORT_TYPE_INT); 1333 mQnsCbsTransportType = 1334 getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_TRANSPORT_TYPE_INT); 1335 mXcapRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_XCAP_RAT_PREFERENCE_INT); 1336 mSosRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_SOS_RAT_PREFERENCE_INT); 1337 mMmsRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_MMS_RAT_PREFERENCE_INT); 1338 mCbsRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_RAT_PREFERENCE_INT); 1339 mNetworkEnableHysteresisTimer = 1340 getConfig( 1341 bundleCarrier, 1342 bundleAsset, 1343 KEY_QNS_IMS_NETWORK_ENABLE_HO_HYSTERESIS_TIMER_INT); 1344 1345 mWwanHysteresisTimer = 1346 getConfig(bundleCarrier, bundleAsset, KEY_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1347 mWlanHysteresisTimer = 1348 getConfig(bundleCarrier, bundleAsset, KEY_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1349 mNonImsWwanHysteresisTimer = 1350 getConfig( 1351 bundleCarrier, bundleAsset, KEY_NON_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1352 mNonImsWlanHysteresisTimer = 1353 getConfig( 1354 bundleCarrier, bundleAsset, KEY_NON_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1355 mMinimumHandoverGuardingTimer = 1356 getConfig(bundleCarrier, bundleAsset, KEY_MINIMUM_HANDOVER_GUARDING_TIMER_MS_INT); 1357 mWaitingTimerForPreferredTransport = 1358 getConfig( 1359 bundleCarrier, 1360 bundleAsset, 1361 KEY_WAITING_TIME_FOR_PREFERRED_TRANSPORT_WHEN_POWER_ON_INT_ARRAY); 1362 mAllowMaxIwlanHoCountOnReason = 1363 getConfig( 1364 bundleCarrier, 1365 bundleAsset, 1366 KEY_QNS_IN_CALL_ROVEIN_ALLOWED_COUNT_AND_FALLBACK_REASON_INT_ARRAY); 1367 mHoRestrictTimeOnRtpQuality = 1368 getConfig( 1369 bundleCarrier, 1370 bundleAsset, 1371 KEY_QNS_HO_RESTRICT_TIME_WITH_LOW_RTP_QUALITY_MILLIS_INT_ARRAY); 1372 mWlanRttBackhaulCheckConfigsOnPing = 1373 getConfig( 1374 bundleCarrier, 1375 bundleAsset, 1376 KEY_QNS_WLAN_RTT_BACKHAUL_CHECK_ON_ICMP_PING_STRING); 1377 1378 mFallbackOnInitialConnectionFailure = 1379 getConfig( 1380 bundleCarrier, 1381 bundleAsset, 1382 KEY_QNS_FALLBACK_ON_INITIAL_CONNECTION_FAILURE_STRING_ARRAY); 1383 mImsAllowedRats = 1384 getConfig(bundleCarrier, bundleAsset, KEY_IMS_CELLULAR_ALLOWED_RAT_STRING_ARRAY); 1385 mRoveInGuardTimerConditionThresholdGaps = 1386 getConfig( 1387 bundleCarrier, 1388 bundleAsset, 1389 KEY_QNS_ROVEIN_THRESHOLD_GAP_WITH_GUARD_TIMER_STRING_ARRAY); 1390 mSipDialogSessionPolicy = 1391 getConfig(bundleCarrier, bundleAsset, KEY_SIP_DIALOG_SESSION_POLICY_INT); 1392 mAccessNetworkMeasurementHysteresisDb = 1393 getConfig( 1394 bundleCarrier, 1395 bundleAsset, 1396 KEY_QNS_CELLULAR_SIGNAL_STRENGTH_HYSTERESIS_DB_STRING_ARRAY); 1397 1398 loadFallbackPolicyWithImsRegiFail(bundleCarrier, bundleAsset); 1399 } 1400 1401 @VisibleForTesting loadWfcConfigurations(PersistableBundle bundleCarrier, PersistableBundle bundleAsset)1402 void loadWfcConfigurations(PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 1403 1404 mVowifiRegistrationTimerForVowifiActivation = 1405 getConfig( 1406 bundleCarrier, 1407 bundleAsset, 1408 KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT); 1409 } 1410 1411 @VisibleForTesting loadFallbackPolicyWithImsRegiFail(PersistableBundle carrier, PersistableBundle asset)1412 void loadFallbackPolicyWithImsRegiFail(PersistableBundle carrier, PersistableBundle asset) { 1413 synchronized (this) { 1414 mFallbackWwanRuleWithImsUnregistered.clear(); 1415 String[] fallbackRulesStrings = 1416 getConfig( 1417 carrier, 1418 asset, 1419 KEY_QNS_FALLBACK_WWAN_IMS_UNREGISTRATION_REASON_STRING_ARRAY); 1420 if (fallbackRulesStrings != null) { 1421 Log.d(mLogTag, "loadFallbackPolicyWithImsRegiFail" + fallbackRulesStrings.length); 1422 for (String ruleString : fallbackRulesStrings) { 1423 Log.d(mLogTag, " ruleString1:" + ruleString); 1424 FallbackRule rule = parseFallbackRule(ruleString); 1425 if (rule != null) { 1426 mFallbackWwanRuleWithImsUnregistered.add(rule); 1427 } 1428 } 1429 } else { 1430 Log.d(mLogTag, "Config FallbackWwanRuleWithImsUnregistered is null"); 1431 } 1432 mFallbackWwanRuleWithImsHoRegisterFail.clear(); 1433 fallbackRulesStrings = 1434 getConfig( 1435 carrier, 1436 asset, 1437 KEY_QNS_FALLBACK_WWAN_IMS_HO_REGISTER_FAIL_REASON_STRING_ARRAY); 1438 if (fallbackRulesStrings != null) { 1439 Log.d(mLogTag, "loadFallbackPolicyWithImsRegiFail2:" + fallbackRulesStrings.length); 1440 for (String ruleString : fallbackRulesStrings) { 1441 Log.d(mLogTag, " ruleString2:" + ruleString); 1442 FallbackRule rule = parseFallbackRule(ruleString); 1443 if (rule != null) { 1444 mFallbackWwanRuleWithImsHoRegisterFail.add(rule); 1445 } 1446 } 1447 } else { 1448 Log.d(mLogTag, "Config mFallbackWwanRuleWithImsHoRegisterFail is null"); 1449 } 1450 } 1451 } 1452 parseFallbackRule(String ruleString)1453 private FallbackRule parseFallbackRule(String ruleString) { 1454 if (TextUtils.isEmpty(ruleString)) { 1455 throw new IllegalArgumentException("illegal rule " + ruleString); 1456 } 1457 Set<Integer> reasons = new ArraySet<>(); 1458 int time = 0; 1459 int preferenceMode = -1; 1460 ruleString = ruleString.trim().toLowerCase(Locale.ROOT); 1461 String[] expressions = ruleString.split("\\s*,\\s*"); 1462 for (String expression : expressions) { 1463 String[] tokens = expression.trim().split("\\s*=\\s*"); 1464 if (tokens.length != 2) { 1465 throw new IllegalArgumentException( 1466 "illegal rule " + ruleString + ", tokens=" + Arrays.toString(tokens)); 1467 } 1468 String key = tokens[0].trim(); 1469 String value = tokens[1].trim(); 1470 1471 try { 1472 switch (key) { 1473 case "cause": 1474 String[] cause = value.trim().split("\\s*\\|\\s*"); 1475 for (String c : cause) { 1476 if (!c.contains("~")) { 1477 reasons.add(Integer.parseInt(c)); 1478 } else { 1479 String[] tok = c.trim().split("\\s*~\\s*"); 1480 int start = Integer.parseInt(tok[0]); 1481 int end = Integer.parseInt(tok[1]); 1482 for (int i = start; i <= end; i++) { 1483 reasons.add(i); 1484 } 1485 } 1486 } 1487 break; 1488 case "time": 1489 time = Integer.parseInt(value); 1490 break; 1491 case "preference": 1492 if (value.equals("cell")) { 1493 preferenceMode = QnsConstants.CELL_PREF; 1494 } else if (value.equals("wifi")) { 1495 preferenceMode = QnsConstants.WIFI_PREF; 1496 } 1497 break; 1498 1499 default: 1500 throw new IllegalArgumentException("unexpected key " + key); 1501 } 1502 1503 } catch (Exception e) { 1504 e.printStackTrace(); 1505 throw new IllegalArgumentException("illegal rule \"" + ruleString + "\", e=" + e); 1506 } 1507 } 1508 if (reasons.size() > 0) { 1509 return new FallbackRule(reasons, time, preferenceMode); 1510 } else { 1511 return null; 1512 } 1513 } 1514 getConfig( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String configKey)1515 private synchronized <T> T getConfig( 1516 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String configKey) { 1517 return QnsUtils.getConfig(bundleCarrier, bundleAsset, configKey); 1518 } 1519 1520 /** Load handover rules from carrier config. */ 1521 @VisibleForTesting loadHandoverRules( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key)1522 void loadHandoverRules( 1523 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key) { 1524 synchronized (this) { 1525 mHandoverRuleList.clear(); 1526 String[] handoverRulesStrings = getConfig(bundleCarrier, bundleAsset, key); 1527 if (handoverRulesStrings != null) { 1528 for (String ruleString : handoverRulesStrings) { 1529 Log.d(mLogTag, "loadHandoverRules: " + ruleString); 1530 try { 1531 mHandoverRuleList.add(new HandoverRule(ruleString)); 1532 } catch (IllegalArgumentException e) { 1533 Log.d(mLogTag, "loadHandoverRules: " + e.getMessage()); 1534 } 1535 } 1536 } 1537 } 1538 } 1539 loadMediaThreshold(PersistableBundle bundleCarrier, PersistableBundle assetConfigBundle)1540 void loadMediaThreshold(PersistableBundle bundleCarrier, PersistableBundle assetConfigBundle) { 1541 //read Jitter 1542 mRTPMetricsData[0] = getConfig( 1543 bundleCarrier, null, 1544 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_JITTER_THRESHOLD_MILLIS_INT); 1545 //read Packet Loss Rate 1546 mRTPMetricsData[1] = getConfig( 1547 bundleCarrier, null, 1548 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT); 1549 //read Inactivity Time 1550 long inactivityTime = getConfig( 1551 bundleCarrier, null, 1552 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG); 1553 mRTPMetricsData[3] = (int) inactivityTime; 1554 //read Packet Loss Duration 1555 mRTPMetricsData[2] = getConfig( 1556 bundleCarrier, assetConfigBundle, 1557 KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT); 1558 } 1559 1560 /** Updated handover rules from carrier config. */ 1561 @VisibleForTesting updateHandoverRules( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key)1562 List<HandoverRule> updateHandoverRules( 1563 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key) { 1564 List<HandoverRule> readNewHandoverRuleList = new ArrayList<>(); 1565 synchronized (this) { 1566 String[] handoverRulesStrings = getConfig(bundleCarrier, bundleAsset, key); 1567 if (handoverRulesStrings != null) { 1568 for (String ruleString : handoverRulesStrings) { 1569 Log.d(mLogTag, "UpdateHandoverRules: " + ruleString); 1570 try { 1571 Log.d(mLogTag, "Rule Updated"); 1572 readNewHandoverRuleList.add(new HandoverRule(ruleString)); 1573 } catch (IllegalArgumentException e) { 1574 Log.d(mLogTag, "UpdateHandoverRules: " + e.getMessage()); 1575 } 1576 } 1577 } 1578 } 1579 return readNewHandoverRuleList; 1580 } 1581 1582 /** Load carrier config. */ 1583 @VisibleForTesting loadCarrierConfig(PersistableBundle bundleCarrier)1584 void loadCarrierConfig(PersistableBundle bundleCarrier) { 1585 mIsMmtelCapabilityRequired = 1586 getConfig( 1587 bundleCarrier, 1588 null, 1589 CarrierConfigManager.Ims.KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY); 1590 mIsVolteRoamingSupported = 1591 getConfig( 1592 bundleCarrier, 1593 null, 1594 CarrierConfigManager.ImsVoice.KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL); 1595 } 1596 1597 /** 1598 * To read the current Carrier ID based on the Slot ID and Context info 1599 * 1600 * @return : Current Carrier ID 1601 */ getCarrierId()1602 int getCarrierId() { 1603 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1604 if (tm != null) { 1605 tm = tm.createForSubscriptionId(QnsUtils.getSubId(mContext, mSlotIndex)); 1606 return tm.getSimCarrierId(); 1607 } 1608 return 0; 1609 } 1610 1611 /** 1612 * To read the current Subscription ID based on the Slot ID and Context info Output : Current 1613 * Carrier ID 1614 */ getSubId()1615 int getSubId() { 1616 mSubId = QnsUtils.getSubId(mContext, mSlotIndex); 1617 return mSubId; 1618 } 1619 1620 /** Notify all the registrants of the Slot loaded after carrier config loading is Completed */ notifyLoadQnsConfigurationsCompleted()1621 protected void notifyLoadQnsConfigurationsCompleted() { 1622 if (mQnsCarrierConfigLoadedRegistrants != null) { 1623 mQnsCarrierConfigLoadedRegistrants.notifyRegistrants(); 1624 } else { 1625 Log.d(mLogTag, "notifyLoadQnsConfigurationsCompleted. no Registrant."); 1626 } 1627 } 1628 1629 /** Notify all the registrants of the Slot loaded after carrier config loading is Completed */ notifyQnsConfigurationsChanged()1630 protected void notifyQnsConfigurationsChanged() { 1631 1632 if (mQnsCarrierConfigChangedRegistrants != null) { 1633 mQnsCarrierConfigChangedRegistrants.notifyRegistrants(); 1634 } else { 1635 Log.d(mLogTag, "notifyQnsConfigurationsChanged. no Registrant."); 1636 } 1637 } 1638 1639 /** 1640 * API exposed for other classes to register for notification with handlers on Carrier 1641 * Configuration Loaded 1642 * 1643 * @param h Handler to receive event 1644 * @param what Event on which to be handled 1645 */ registerForConfigurationLoaded(Handler h, int what)1646 void registerForConfigurationLoaded(Handler h, int what) { 1647 mQnsCarrierConfigLoadedRegistrants.addUnique(h, what, null); 1648 if (mIsConfigLoaded) { 1649 // notify the handler if config is already loaded. 1650 h.sendEmptyMessage(what); 1651 } 1652 } 1653 1654 /** 1655 * API exposed for other classes to register for notification with handlers on Carrier 1656 * Configuration changed 1657 * 1658 * @param h Handler to receive event 1659 * @param what Event on which to be handled 1660 */ registerForConfigurationChanged(Handler h, int what)1661 void registerForConfigurationChanged(Handler h, int what) { 1662 mQnsCarrierConfigChangedRegistrants.addUnique(h, what, null); 1663 } 1664 1665 /** 1666 * API exposed for other classes to unregister for notification of QNS Configuration loaded with 1667 * handlers 1668 * 1669 * @param h Handler to Unregister receiving event Output : Void 1670 */ unregisterForConfigurationLoaded(Handler h)1671 void unregisterForConfigurationLoaded(Handler h) { 1672 mQnsCarrierConfigLoadedRegistrants.remove(h); 1673 } 1674 1675 /** 1676 * API exposed for other classes to unregister for notification of QNS Configuration changed 1677 * with handlers 1678 * 1679 * @param h Handler to Unregister receiving event Output : Void 1680 */ unregisterForConfigurationChanged(Handler h)1681 void unregisterForConfigurationChanged(Handler h) { 1682 mQnsCarrierConfigChangedRegistrants.remove(h); 1683 } 1684 1685 /** 1686 * This method returns if WFC is supported in Airplane Mode On 1687 * 1688 * @return : boolean (True/False) 1689 */ allowWFCOnAirplaneModeOn()1690 boolean allowWFCOnAirplaneModeOn() { 1691 1692 return mIsWfcInAirplaneModeOnSupport; 1693 } 1694 1695 /** 1696 * This method returns if in-call handover decision from WLAN to WWAN should not consider VoPS 1697 * status. 1698 * 1699 * @return True if in-call handover decision from WLAN to WWAN should not consider VoPS status, 1700 * otherwise false. 1701 */ isInCallHoDecisionWlanToWwanWithoutVopsCondition()1702 boolean isInCallHoDecisionWlanToWwanWithoutVopsCondition() { 1703 return mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported; 1704 } 1705 1706 /** 1707 * This method returns VOPS/VONR bit is required for WWAN availability. 1708 * 1709 * @return : boolean (True/False) 1710 */ isMmtelCapabilityRequired(int coverage)1711 boolean isMmtelCapabilityRequired(int coverage) { 1712 if (mIsMmtelCapabilityRequired == null || mIsMmtelCapabilityRequired.length == 0) { 1713 return true; 1714 } 1715 for (int i : mIsMmtelCapabilityRequired) { 1716 if ((i == CarrierConfigManager.Ims.NETWORK_TYPE_HOME 1717 && coverage == QnsConstants.COVERAGE_HOME) 1718 || (i == CarrierConfigManager.Ims.NETWORK_TYPE_ROAMING 1719 && coverage == QnsConstants.COVERAGE_ROAM)) { 1720 return false; 1721 } 1722 } 1723 return true; 1724 } 1725 1726 /** 1727 * This method returns if VoLTE roaming is supported by a carrier. 1728 * 1729 * @return True if VoLTE roaming is supported or UE is in home network, otherwise false. 1730 */ isVolteRoamingSupported(@nsConstants.CellularCoverage int coverage)1731 boolean isVolteRoamingSupported(@QnsConstants.CellularCoverage int coverage) { 1732 if (coverage == QnsConstants.COVERAGE_ROAM) { 1733 return mIsVolteRoamingSupported; 1734 } 1735 return true; 1736 } 1737 1738 /** 1739 * This method returns Video call over WFC with wfc off & LTE preconditions met 1740 * 1741 * @return : boolean (True/False) 1742 */ allowVideoOverIWLANWithCellularLimitedCase()1743 boolean allowVideoOverIWLANWithCellularLimitedCase() { 1744 return mIsVideoOverIWLANWithCellularCheckSupport; 1745 } 1746 1747 /** 1748 * This method returns if handover is allowed by policy 1749 * 1750 * @return True if handover is allowed by policy, otherwise false. 1751 */ isHandoverAllowedByPolicy( int netCapability, int srcAn, int destAn, @QnsConstants.CellularCoverage int coverage)1752 boolean isHandoverAllowedByPolicy( 1753 int netCapability, int srcAn, int destAn, @QnsConstants.CellularCoverage int coverage) { 1754 Log.d( 1755 mLogTag, 1756 "isHandoverAllowedByPolicy netCapability: " 1757 + QnsUtils.getNameOfNetCapability(netCapability) 1758 + " srcAccessNetwork:" 1759 + QnsConstants.accessNetworkTypeToString(srcAn) 1760 + " destAccessNetwork:" 1761 + QnsConstants.accessNetworkTypeToString(destAn) 1762 + " " 1763 + QnsConstants.coverageToString(coverage)); 1764 // check Telephony handover policy. 1765 // Matching the rules by the configured order. Bail out if find first matching rule. 1766 for (HandoverRule rule : mHandoverRuleList) { 1767 if (rule.mIsOnlyForRoaming && coverage != QnsConstants.COVERAGE_ROAM) continue; 1768 1769 if (rule.mSourceAccessNetworks.contains(srcAn) 1770 && rule.mTargetAccessNetworks.contains(destAn)) { 1771 // if no capability rule specified, data network capability is considered matched. 1772 // otherwise, any capabilities overlap is also considered matched. 1773 if (rule.mNetworkCapabilities.isEmpty() 1774 || rule.mNetworkCapabilities.contains(netCapability)) { 1775 if (rule.mHandoverRuleType == HandoverRule.RULE_TYPE_DISALLOWED) { 1776 Log.d(mLogTag, "isHandoverAllowedByPolicy:Not allowed by policy " + rule); 1777 return false; 1778 } else { 1779 Log.d(mLogTag, "isHandoverAllowedByPolicy: allowed by policy " + rule); 1780 return true; 1781 } 1782 } 1783 } 1784 } 1785 1786 Log.d(mLogTag, "isHandoverAllowedByPolicy: Did not find matching rule. "); 1787 // Disallow handover for non-IMS network capability anyway if no rule is found. 1788 if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) return false; 1789 1790 // Allow handover for IMS network capability anyway if no rule is found. 1791 return true; 1792 } 1793 1794 /** 1795 * This method returns if Service Barring Check for HO decision is Supported 1796 * 1797 * @return : boolean (True/False) 1798 */ isServiceBarringCheckSupported()1799 boolean isServiceBarringCheckSupported() { 1800 1801 return mIsServiceBarringCheckSupport; 1802 } 1803 1804 /** 1805 * This method returns if the Guard timer (Ping Pong) hysteresis is preference specific 1806 * 1807 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1808 * True / False 1809 */ isGuardTimerHysteresisOnPrefSupported()1810 boolean isGuardTimerHysteresisOnPrefSupported() { 1811 1812 return mIsHoGuardOnPreferenceSupport; 1813 } 1814 1815 /** 1816 * This method returns if the network(HOME or ROAM) requires handover guard timer. 1817 * 1818 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1819 * True / False 1820 */ isHysteresisTimerEnabled(int coverage)1821 boolean isHysteresisTimerEnabled(int coverage) { 1822 if (mNetworkEnableHysteresisTimer == QnsConstants.COVERAGE_BOTH 1823 || mNetworkEnableHysteresisTimer == coverage) { 1824 return true; 1825 } 1826 return false; 1827 } 1828 1829 /** 1830 * Get carrier config for the KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL if 1831 * true, It ignores all thresholds needed to only refer to availability. 1832 * 1833 * @return true for key value is true. False for otherwise. 1834 */ isTransportTypeSelWithoutSSInRoamSupported()1835 boolean isTransportTypeSelWithoutSSInRoamSupported() { 1836 1837 return mAnspSupportConfigArray[0]; 1838 } 1839 1840 /* 1841 * get carrierconfig for KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL 1842 * true: Prefer current transport type during voice call. 1843 * 1844 * @return true for key value is true. False for otherwise. 1845 */ isCurrentTransportTypeInVoiceCallSupported()1846 boolean isCurrentTransportTypeInVoiceCallSupported() { 1847 1848 return mAnspSupportConfigArray[1]; 1849 } 1850 1851 /** 1852 * Get carrierconfig for KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL 1853 * true: Use IMS Preferred when WFC Mode is Cellular Preferred at Home Network. 1854 * 1855 * @return true for key value is true. False for otherwise. 1856 */ isOverrideImsPreferenceSupported()1857 boolean isOverrideImsPreferenceSupported() { 1858 return mAnspSupportConfigArray[2]; 1859 } 1860 1861 /** 1862 * The method is to return if choose WFC prferred transport in both WWAN and WLAN are bad 1863 * conditions. It is controlled by 1864 * KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY. 1865 * 1866 * @return : boolean (True/False) 1867 */ isChooseWfcPreferredTransportInBothBadCondition(int wfcMode)1868 boolean isChooseWfcPreferredTransportInBothBadCondition(int wfcMode) { 1869 if (mIsWfcPreferredTransportRequired == null 1870 || mIsWfcPreferredTransportRequired.length == 0) { 1871 return false; 1872 } 1873 for (int i : mIsWfcPreferredTransportRequired) { 1874 if (wfcMode == i) { 1875 return true; 1876 } 1877 } 1878 return false; 1879 } 1880 1881 /** 1882 * This method returns whether the rove out(to Cellular) policy includes a Wi-Fi bad condition 1883 * at handover guarding time. 1884 * 1885 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1886 * True / False 1887 */ isRoveOutWithWiFiLowQualityAtGuardingTime()1888 boolean isRoveOutWithWiFiLowQualityAtGuardingTime() { 1889 1890 return mIsRoveOutWifiBadGuardTimerConditionsSupported; 1891 } 1892 1893 /** 1894 * This method returns the waiting time for the preferred transport type at power up. 1895 * 1896 * @return : A timer in millisecond 1897 */ getWaitingTimerForPreferredTransportOnPowerOn(int transportType)1898 int getWaitingTimerForPreferredTransportOnPowerOn(int transportType) { 1899 switch (transportType) { 1900 case TRANSPORT_TYPE_WWAN: 1901 return mWaitingTimerForPreferredTransport[0]; 1902 case TRANSPORT_TYPE_WLAN: 1903 return mWaitingTimerForPreferredTransport[1]; 1904 default: 1905 Log.d(mLogTag, "Invalid transport type, return the default timer."); 1906 return QnsConstants.KEY_DEFAULT_VALUE; 1907 } 1908 } 1909 1910 /** 1911 * This method returns the Transport type Preference on Power On. 1912 * 1913 * @return : Based on Carrier Config Settings Possible values (3000msec:Default or operator 1914 * customisation. 1915 */ getWIFIRssiBackHaulTimer()1916 int getWIFIRssiBackHaulTimer() { 1917 return mWifiThresBackHaulTimer; 1918 } 1919 1920 /** 1921 * This method returns Cellular SS Backhaul Timer. 1922 * 1923 * @return : Based on Carrier Config Settings based on operator requirement possible values ( 0 1924 * : Invalid or 320ms) 1925 */ getCellularSSBackHaulTimer()1926 int getCellularSSBackHaulTimer() { 1927 1928 return mCellularThresBackHaulTimer; 1929 } 1930 1931 /** 1932 * This method returns IWLAN HO Avoid time due to Low RTP Quality Backhaul Timer. 1933 * 1934 * @return : Based on Carrier Config Settings based on operator requirement possible values ( 0 1935 * : or operator requirement) 1936 */ getHoRestrictedTimeOnLowRTPQuality( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork)1937 int getHoRestrictedTimeOnLowRTPQuality( 1938 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork) { 1939 1940 if (accessNetwork == TRANSPORT_TYPE_WLAN) { 1941 return mHoRestrictTimeOnRtpQuality[0]; 1942 } else if (accessNetwork == TRANSPORT_TYPE_WWAN) { 1943 return mHoRestrictTimeOnRtpQuality[1]; 1944 } else { 1945 return QnsConstants.KEY_DEFAULT_VALUE; 1946 } 1947 } 1948 1949 /** 1950 * This method returns QNS preferred transport type for network capabilities / Services 1951 * 1952 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1953 * TRANSPORT_TYPE_ALLOWED_WWAN = 0 TRANSPORT_TYPE_ALLOWED_IWLAN = 1 1954 * TRANSPORT_TYPE_ALLOWED_BOTH = 2 1955 */ getQnsSupportedTransportType(int netCapability)1956 int getQnsSupportedTransportType(int netCapability) { 1957 if (netCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 1958 return mQnsImsTransportType; 1959 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) { 1960 return mQnsSosTransportType; 1961 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_MMS) { 1962 return mQnsMmsTransportType; 1963 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_XCAP) { 1964 HashSet<Integer> supportedTransportType = new HashSet<>(); 1965 if (mQnsXcapSupportedAccessNetworkTypes != null) { 1966 Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 1967 .forEach(accessNetwork -> supportedTransportType.add( 1968 QnsUtils.getTransportTypeFromAccessNetwork(accessNetwork))); 1969 } 1970 if (supportedTransportType.contains(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)) { 1971 if (supportedTransportType.contains(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) { 1972 return QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH; 1973 } 1974 return QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN; 1975 } 1976 return QnsConstants.TRANSPORT_TYPE_ALLOWED_WWAN; 1977 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_CBS) { 1978 return mQnsCbsTransportType; 1979 } 1980 return QnsConstants.INVALID_ID; 1981 } 1982 1983 /** 1984 * This method returns the hysteresis timer when handover from WLAN to WWAN. 1985 * 1986 * @return : the hysteresis timer 1987 */ getWwanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType)1988 int getWwanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType) { 1989 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC)) { 1990 return mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC); 1991 } 1992 switch (netCapability) { 1993 case NetworkCapabilities.NET_CAPABILITY_IMS: 1994 case NetworkCapabilities.NET_CAPABILITY_EIMS: 1995 if (callType == QnsConstants.CALL_TYPE_IDLE) { 1996 return mWwanHysteresisTimer[0]; 1997 } else if (callType == QnsConstants.CALL_TYPE_VOICE) { 1998 return mWwanHysteresisTimer[1]; 1999 } else if (callType == QnsConstants.CALL_TYPE_VIDEO) { 2000 return mWwanHysteresisTimer[2]; 2001 } else { 2002 return QnsConstants.KEY_DEFAULT_VALUE; 2003 } 2004 case NetworkCapabilities.NET_CAPABILITY_MMS: 2005 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2006 case NetworkCapabilities.NET_CAPABILITY_CBS: 2007 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2008 return mNonImsWwanHysteresisTimer[0]; 2009 } else { 2010 return mNonImsWwanHysteresisTimer[1]; 2011 } 2012 default: 2013 return QnsConstants.KEY_DEFAULT_VALUE; 2014 } 2015 } 2016 2017 /** 2018 * This method returns the hysteresis timer when handover from WWAN to WLAN. 2019 * 2020 * @return : the hysteresis timer 2021 */ getWlanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType)2022 int getWlanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType) { 2023 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC)) { 2024 return mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC); 2025 } 2026 switch (netCapability) { 2027 case NetworkCapabilities.NET_CAPABILITY_IMS: 2028 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2029 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2030 return mWlanHysteresisTimer[0]; 2031 } else if (callType == QnsConstants.CALL_TYPE_VOICE) { 2032 return mWlanHysteresisTimer[1]; 2033 } else if (callType == QnsConstants.CALL_TYPE_VIDEO) { 2034 return mWlanHysteresisTimer[2]; 2035 } else { 2036 return QnsConstants.KEY_DEFAULT_VALUE; 2037 } 2038 case NetworkCapabilities.NET_CAPABILITY_MMS: 2039 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2040 case NetworkCapabilities.NET_CAPABILITY_CBS: 2041 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2042 return mNonImsWlanHysteresisTimer[0]; 2043 } else { 2044 return mNonImsWlanHysteresisTimer[1]; 2045 } 2046 default: 2047 return QnsConstants.KEY_DEFAULT_VALUE; 2048 } 2049 } 2050 2051 /** 2052 * This method returns the timer millis for the minimum guarding timer. 2053 * 2054 * @return the minimum guarding timer in millis. applies when handover guarding is disabled or 2055 * there is no guarding time. 2056 */ getMinimumHandoverGuardingTimer()2057 int getMinimumHandoverGuardingTimer() { 2058 int timer = mMinimumHandoverGuardingTimer; 2059 if (timer <= 0) { 2060 return 0; 2061 } 2062 if (timer >= QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT) { 2063 timer = QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT; 2064 } 2065 return timer; 2066 } 2067 2068 /** 2069 * This method returns the Threshold gap offset based on which threshold to be registered during 2070 * Guard timer Running / Expired conditions from Evaluator 2071 * 2072 * @return : Based on Carrier Config Settings & operator requirement Default Value : 0 gap 2073 * offset (Means different threshold for Guard timer conditions not enabled) 2074 */ getThresholdGapWithGuardTimer( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType)2075 int getThresholdGapWithGuardTimer( 2076 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType) { 2077 2078 return getValueForMeasurementType( 2079 accessNetwork, measType, mRoveInGuardTimerConditionThresholdGaps); 2080 2081 } 2082 2083 /** 2084 * This method returns hysteresis Dbm level for ran and measurement type configured. 2085 * 2086 * @return : Based on Carrier Config Settings & operator requirement Default Value. 2087 * Note: If configured value set is less than zero or not set, 2088 * {@link QnsConstants#KEY_DEFAULT_VALUE} 2089 */ getWwanHysteresisDbLevel( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType)2090 public int getWwanHysteresisDbLevel( 2091 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType) { 2092 2093 int hysteresisDb = getValueForMeasurementType( 2094 accessNetwork, measType, mAccessNetworkMeasurementHysteresisDb); 2095 return hysteresisDb >= 0 ? hysteresisDb : QnsConstants.KEY_DEFAULT_VALUE; 2096 } 2097 getValueForMeasurementType( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType, String [] measurementValues)2098 private int getValueForMeasurementType( 2099 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType, 2100 String [] measurementValues) { 2101 2102 if (measurementValues == null) { 2103 return QnsConstants.KEY_DEFAULT_VALUE; 2104 } 2105 2106 for (String check_offset : measurementValues) { 2107 if (check_offset == null || check_offset.isEmpty()) continue; 2108 String[] value = check_offset.split(":"); 2109 String access_network = sAccessNetworkMap.get(accessNetwork); 2110 String measurement_Type = sMeasTypeMap.get(measType); 2111 try { 2112 if (value.length == 3 && value[0].equalsIgnoreCase(access_network) 2113 && value[1].equalsIgnoreCase(measurement_Type)) { 2114 return Integer.parseInt(value[2]); 2115 } 2116 } catch (Exception e) { 2117 e.printStackTrace(); 2118 } 2119 } 2120 return QnsConstants.KEY_DEFAULT_VALUE; 2121 } 2122 hasThresholdGapWithGuardTimer()2123 boolean hasThresholdGapWithGuardTimer() { 2124 if (mRoveInGuardTimerConditionThresholdGaps == null) { 2125 return false; 2126 } 2127 return true; 2128 } 2129 2130 /** 2131 * This method returns Access Network Selection Policy based on network capability 2132 * 2133 * @param targetTransportType : WWAN/WLAN 2134 * @return : Target transport mapped to string 2135 */ transportNetworkToString(int targetTransportType)2136 static String transportNetworkToString(int targetTransportType) { 2137 switch (targetTransportType) { 2138 case TRANSPORT_TYPE_WWAN: 2139 return "CELLULAR"; 2140 case TRANSPORT_TYPE_WLAN: 2141 return "WIFI"; 2142 } 2143 return ""; 2144 } 2145 2146 /** 2147 * Finds and returns a threshold config that meets the given parameter condition. 2148 * 2149 * @param accessNetwork (EUTRAN/UTRAN/NGRAN/GERAN/IWLAN) 2150 * @param callType (IDLE/VOICE/VIDEO) 2151 * @param measurementType (RSRP/RSRQ/RSSNR/SSRSP/SSRSQ/RSCP/RSSI) 2152 * @return QnsConfigArray for good, bad and worst thresholds. If the value does not exist or is 2153 * not supported, it is filled with invalid (0x0000FFFF). Note, for the wifi case, the worst 2154 * in thresholds will be invalid. INVALID VALUE, if not found item or exceptions. 2155 */ getThreshold( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int callType, int measurementType)2156 QnsConfigArray getThreshold( 2157 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, 2158 int callType, 2159 int measurementType) { 2160 int[] thresholdList = new int[] {0x0000FFFF, 0x0000FFFF, 0x0000FFFF}; 2161 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.UNKNOWN 2162 || measurementType == SIGNAL_MEASUREMENT_TYPE_UNKNOWN) { 2163 return null; 2164 } 2165 2166 String access_network = sAccessNetworkMap.get(accessNetwork); 2167 String measurement_Type = sMeasTypeMap.get(measurementType); 2168 String call_Type = sCallTypeMap.get(callType); 2169 2170 if (access_network != null && measurement_Type != null && call_Type != null) { 2171 String key = 2172 "qns." 2173 + call_Type 2174 + "_" 2175 + access_network 2176 + "_" 2177 + measurement_Type 2178 + "_" 2179 + "int_array"; 2180 2181 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2182 2183 if (thresholdList != null && thresholdList.length > 1) { 2184 if (AccessNetworkConstants.AccessNetworkType.IWLAN == accessNetwork 2185 || thresholdList.length == 2) { 2186 return new QnsConfigArray(thresholdList[0], thresholdList[1]); 2187 } else { 2188 return new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2189 } 2190 } else { 2191 thresholdList = new int[] {0x0000FFFF, 0x0000FFFF, 0x0000FFFF}; 2192 } 2193 } 2194 return new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2195 } 2196 getThresholdByPref( int accessNetwork, int callType, int measurementType, int preference)2197 QnsConfigArray getThresholdByPref( 2198 int accessNetwork, int callType, int measurementType, int preference) { 2199 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.UNKNOWN 2200 || measurementType == SIGNAL_MEASUREMENT_TYPE_UNKNOWN) { 2201 return null; 2202 } 2203 2204 int[] thresholdList = null; 2205 String access_network = sAccessNetworkMap.get(accessNetwork); 2206 String measurement_Type = sMeasTypeMap.get(measurementType); 2207 String call_Type = sCallTypeMap.get(callType); 2208 2209 if (access_network == null || measurement_Type == null || call_Type == null) { 2210 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2211 } 2212 2213 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 2214 && preference == QnsConstants.WIFI_PREF) { 2215 String overrideKey = 2216 "qns.override_wifi_pref_" 2217 + call_Type 2218 + "_" 2219 + access_network 2220 + "_" 2221 + measurement_Type 2222 + "_int_array"; 2223 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(overrideKey); 2224 } 2225 2226 if (thresholdList == null || thresholdList.length < 2) { 2227 String key = 2228 "qns." 2229 + call_Type 2230 + "_" 2231 + access_network 2232 + "_" 2233 + measurement_Type 2234 + "_int_array"; 2235 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2236 } 2237 if (thresholdList == null || thresholdList.length < 2) { 2238 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2239 } 2240 2241 if (AccessNetworkConstants.AccessNetworkType.IWLAN == accessNetwork 2242 || thresholdList.length == 2) { 2243 QnsConfigArray qnsConfigArray = new QnsConfigArray(thresholdList[0], thresholdList[1]); 2244 return applyProvisioningInfo(qnsConfigArray, accessNetwork, measurementType, callType); 2245 } 2246 2247 QnsConfigArray qnsConfigArray = 2248 new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2249 return applyProvisioningInfo(qnsConfigArray, accessNetwork, measurementType, callType); 2250 } 2251 getWifiRssiThresholdWithoutCellular(int callType)2252 QnsConfigArray getWifiRssiThresholdWithoutCellular(int callType) { 2253 int[] thresholdList; 2254 String call_Type = sCallTypeMap.get(callType); 2255 2256 if (call_Type == null) { 2257 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2258 } 2259 2260 String key = "qns." + call_Type + "_wifi_rssi_without_cellular_int_array"; 2261 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2262 2263 if (thresholdList == null || thresholdList.length < 2) { 2264 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2265 } 2266 2267 return new QnsConfigArray(thresholdList[0], thresholdList[1]); 2268 } 2269 2270 /** 2271 * Finds and returns a policy config that meets the given parameter condition. 2272 * 2273 * @param direction (ROVE_IN / ROVE_OUT) 2274 * @param preCondition (Types of CALL, PREFERENCE, COVERAGE and so on) 2275 * @return QnsConfigArray for good, bad and worst policy. If the value does not exist or is not 2276 * supported, it is filled with invalid. (0x0000FFFF). Note, for the wifi case, the worst in 2277 * thresholds will be invalid. null, if not found item or exceptions. 2278 */ getPolicy( @nsConstants.RoveDirection int direction, AccessNetworkSelectionPolicy.PreCondition preCondition)2279 String[] getPolicy( 2280 @QnsConstants.RoveDirection int direction, 2281 AccessNetworkSelectionPolicy.PreCondition preCondition) { 2282 2283 String key = 2284 "qns.condition_" 2285 + QnsConstants.directionToString(direction).toLowerCase() 2286 + "_" 2287 + QnsConstants.callTypeToString(preCondition.getCallType()).toLowerCase() 2288 + "_" 2289 + QnsConstants.preferenceToString(preCondition.getPreference()) 2290 .toLowerCase() 2291 + "_" 2292 + QnsConstants.coverageToString(preCondition.getCoverage()).toLowerCase() 2293 + "_"; 2294 2295 if (preCondition instanceof AccessNetworkSelectionPolicy.GuardingPreCondition) { 2296 AccessNetworkSelectionPolicy.GuardingPreCondition guardingCondition = 2297 (AccessNetworkSelectionPolicy.GuardingPreCondition) preCondition; 2298 String guardingKey = 2299 key 2300 + QnsConstants.guardingToString(guardingCondition.getGuarding()) 2301 .toLowerCase() 2302 + "_string_array"; 2303 String[] guardingPolicy = mAnspConfigMgr.getAnspCarrierPolicy(guardingKey); 2304 if (guardingPolicy != null) { 2305 return guardingPolicy; 2306 } 2307 } 2308 key = key + "string_array"; 2309 return mAnspConfigMgr.getAnspCarrierPolicy(key); 2310 } 2311 2312 /** 2313 * This method returns RTP Metrics data of Carrier for HO decision making 2314 * 2315 * @return config of RTP metrics. refer {@link RtpMetricsConfig} 2316 */ 2317 @VisibleForTesting getRTPMetricsData()2318 RtpMetricsConfig getRTPMetricsData() { 2319 2320 return new RtpMetricsConfig( 2321 mRTPMetricsData[0], mRTPMetricsData[1], mRTPMetricsData[2], mRTPMetricsData[3]); 2322 } 2323 2324 /** 2325 * This retrieves fallback timer to WWAN with the reason of IMS unregistered. 2326 * 2327 * @return fallback time in millis. 2328 */ 2329 @VisibleForTesting getFallbackTimeImsUnregistered(int reason, int preferMode)2330 int getFallbackTimeImsUnregistered(int reason, int preferMode) { 2331 Log.d( 2332 mLogTag, 2333 "getFallbackTimeImsUnregistered reason:" + reason + " prefMode:" + preferMode); 2334 for (FallbackRule rule : mFallbackWwanRuleWithImsUnregistered) { 2335 Log.d(mLogTag, rule.toString()); 2336 if (preferMode != QnsConstants.WIFI_ONLY 2337 && (rule.mPreferenceMode == -1 || rule.mPreferenceMode == preferMode)) { 2338 int time = rule.getFallBackTime(reason); 2339 if (time > 0) { 2340 Log.d(mLogTag, "getFallbackTimeImsUnregistered fallbackTime:" + time); 2341 return time; 2342 } 2343 } 2344 } 2345 Log.d(mLogTag, "getFallbackTimeImsUnregistered fallbackTime:" + 0); 2346 return 0; 2347 } 2348 2349 /** 2350 * This retrieves fallback timer to WWAN with the reason of IMS HO register fail. 2351 * 2352 * @return fallback time in millis. 2353 */ 2354 @VisibleForTesting getFallbackTimeImsHoRegisterFailed(int reason, int preferMode)2355 int getFallbackTimeImsHoRegisterFailed(int reason, int preferMode) { 2356 Log.d( 2357 mLogTag, 2358 "getFallbackTimeImsHoRegisterFailed reason:" + reason + " prefMode:" + preferMode); 2359 for (FallbackRule rule : mFallbackWwanRuleWithImsHoRegisterFail) { 2360 if (preferMode != QnsConstants.WIFI_ONLY 2361 && (rule.mPreferenceMode == -1 || rule.mPreferenceMode == preferMode)) { 2362 Log.d(mLogTag, rule.toString()); 2363 int time = rule.getFallBackTime(reason); 2364 Log.d(mLogTag, "getFallbackTimeImsHoRegisterFailed fallback time: " + time); 2365 if (time > 0) return time; 2366 } 2367 } 2368 Log.d(mLogTag, "getFallbackTimeImsHoRegisterFailed fallback time: " + 0); 2369 return 0; 2370 } 2371 2372 /** 2373 * This method returns Access Network Selection Policy Support configurations with boolean array 2374 * list type 2375 * 2376 */ loadAnspCarrierSupportConfigs( PersistableBundle bundleCarrier, PersistableBundle bundleAsset)2377 void loadAnspCarrierSupportConfigs( 2378 PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 2379 int i = 0; 2380 String[] anspConfigs = { 2381 KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL, 2382 KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL_BOOL, 2383 KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL 2384 }; 2385 2386 for (String key : anspConfigs) { 2387 mAnspSupportConfigArray[i] = getConfig(bundleCarrier, bundleAsset, key); 2388 i += 1; 2389 } 2390 2391 mIsWfcPreferredTransportRequired = 2392 getConfig( 2393 bundleCarrier, 2394 bundleAsset, 2395 KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY); 2396 } 2397 2398 /** 2399 * This method gives the network capabilities supported based on 2400 * KEY_QNS_<NetworkCapability></NetworkCapability>_TRANSPORT_TYPE_INT 2401 * 2402 * @return : Supported network capabilities 2403 */ getQnsSupportedNetCapabilities()2404 List<Integer> getQnsSupportedNetCapabilities() { 2405 List<Integer> netCapabilities = new ArrayList<>(); 2406 if (mQnsImsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2407 || mQnsImsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2408 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_IMS); 2409 } 2410 if (mQnsSosTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2411 || mQnsSosTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2412 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_EIMS); 2413 } 2414 if (mQnsMmsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2415 || mQnsMmsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2416 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_MMS); 2417 } 2418 if (mQnsXcapSupportedAccessNetworkTypes != null 2419 && Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 2420 .anyMatch(accessNetwork -> QnsUtils.getTransportTypeFromAccessNetwork( 2421 accessNetwork) == AccessNetworkConstants.TRANSPORT_TYPE_WLAN)) { 2422 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_XCAP); 2423 } 2424 if (mQnsCbsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2425 || mQnsCbsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2426 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_CBS); 2427 } 2428 return netCapabilities; 2429 } 2430 2431 private static final Map<Integer, String> sRatStringMatcher = Map.of( 2432 AccessNetworkConstants.AccessNetworkType.EUTRAN, "LTE", 2433 AccessNetworkConstants.AccessNetworkType.NGRAN, "NR", 2434 AccessNetworkConstants.AccessNetworkType.UTRAN, "3G", 2435 AccessNetworkConstants.AccessNetworkType.GERAN, "2G" 2436 ); 2437 2438 /** 2439 * This method returns Allowed cellular RAT for IMS 2440 * 2441 * @param accessNetwork : (EUTRAN, NGRAN, UTRAN, GERAN) 2442 * @param netCapability : (ims, sos, mms, xcap, cbs) 2443 * @return : True or False based on configuration 2444 */ isAccessNetworkAllowed(int accessNetwork, int netCapability)2445 boolean isAccessNetworkAllowed(int accessNetwork, int netCapability) { 2446 2447 switch (netCapability) { 2448 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2449 case NetworkCapabilities.NET_CAPABILITY_IMS: 2450 // cases to be enhanced for different key items when added 2451 String ratName = sRatStringMatcher.get(accessNetwork); 2452 if (mImsAllowedRats != null 2453 && ratName != null 2454 && Arrays.stream(mImsAllowedRats) 2455 .anyMatch(ratType -> TextUtils.equals(ratType, ratName))) { 2456 return true; 2457 } 2458 break; 2459 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2460 return mQnsXcapSupportedAccessNetworkTypes != null 2461 && Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 2462 .anyMatch(xcapAccessNetwork -> accessNetwork == xcapAccessNetwork); 2463 default: 2464 return false; 2465 } 2466 return false; 2467 } 2468 2469 /** 2470 * This method returns max HO Back to IWLAN count value with Fallback reason to Rove Out 2471 * 2472 * @return : int array (Ex: -1,-1 or 1,2 or 3,1 etc... ) 2473 */ getQnsMaxIwlanHoCountDuringCall()2474 int getQnsMaxIwlanHoCountDuringCall() { 2475 2476 if (mAllowMaxIwlanHoCountOnReason[0] <= 0) { 2477 mAllowMaxIwlanHoCountOnReason[0] = MAX_COUNT_INVALID; 2478 } 2479 2480 return mAllowMaxIwlanHoCountOnReason[0]; 2481 } 2482 2483 /** 2484 * This method returns Supported Fallback reason to Rove Out from IWLAN 2485 * 2486 * @return : int array (Ex: -1,-1 or 1,2 or 3,1 etc... ) 2487 */ getQnsIwlanHoRestrictReason()2488 int getQnsIwlanHoRestrictReason() { 2489 if (mAllowMaxIwlanHoCountOnReason[1] <= 0) { 2490 mAllowMaxIwlanHoCountOnReason[1] = FALLBACK_REASON_INVALID; 2491 } 2492 return mAllowMaxIwlanHoCountOnReason[1]; 2493 } 2494 2495 /** 2496 * This method returns to allow enabled Wi-Fi calling based on exceptional cellular state, even 2497 * when Wi-Fi calling is disabled. 2498 * 2499 * <p>Enable Wi-Fi calling If the call state is idle and the cellular network the UE is staying 2500 * on does not allow ims pdn. 2501 * 2502 * @return : Based on Carrier Config Settings based on operator requirement possible values: 2503 * True / False 2504 */ allowImsOverIwlanCellularLimitedCase()2505 boolean allowImsOverIwlanCellularLimitedCase() { 2506 return mIsAllowImsOverIwlanCellularLimitedCase; 2507 } 2508 2509 /** 2510 * This method returns if Iwlan is not allowed when UE is in no WWAN coverage and the last 2511 * stored country code is outside the home country. 2512 * 2513 * @return True if need to block Iwlan, otherwise false. 2514 */ blockIwlanInInternationalRoamWithoutWwan()2515 boolean blockIwlanInInternationalRoamWithoutWwan() { 2516 return mIsBlockIwlanInInternationalRoamWithoutWwan; 2517 } 2518 2519 /** 2520 * This method returns if IPv6 only WiFi is allowed 2521 * 2522 * @return True if need to block IPv6 only WiFi, otherwise false. 2523 */ blockIpv6OnlyWifi()2524 boolean blockIpv6OnlyWifi() { 2525 return mIsBlockIpv6OnlyWifi; 2526 } 2527 2528 /** 2529 * This method returns the wait timer in milliseconds that VoWiFi registration in VoWiFi 2530 * activation process 2531 */ getVowifiRegistrationTimerForVowifiActivation()2532 int getVowifiRegistrationTimerForVowifiActivation() { 2533 return mVowifiRegistrationTimerForVowifiActivation; 2534 } 2535 2536 /** 2537 * This method returns whether the IMS Registration state option is added when reporting a 2538 * qualified Wi-Fi network for network capabilities other than ims. 2539 * 2540 * @return : Based on Carrier Config Settings based on operator requirement possible values: 2541 * True / False 2542 */ getRatPreference(int netCapability)2543 int getRatPreference(int netCapability) { 2544 switch (netCapability) { 2545 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2546 return mXcapRatPreference; 2547 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2548 return mSosRatPreference; 2549 case NetworkCapabilities.NET_CAPABILITY_MMS: 2550 return mMmsRatPreference; 2551 case NetworkCapabilities.NET_CAPABILITY_CBS: 2552 return mCbsRatPreference; 2553 } 2554 return QnsConstants.RAT_PREFERENCE_DEFAULT; 2555 } 2556 2557 /** 2558 * This method returns the rtt check server address config as per operator requirement 2559 * 2560 * @return Based on carrier config settings of operator. By default, to be made empty to 2561 * disable the feature. 2562 */ getWlanRttServerAddressConfig()2563 String getWlanRttServerAddressConfig() { 2564 String[] ping_address = getWlanRttPingConfigs(); 2565 2566 if (ping_address != null && ping_address[0] != null && !ping_address[0].isEmpty()) { 2567 return ping_address[0]; 2568 } else { 2569 return null; 2570 } 2571 } 2572 2573 /** 2574 * This method returns No of Pings, Intra Ping Interval, Size of the packet, RTT criteria RTT 2575 * retry timer 2576 * 2577 * @return : Based on carrier config settings as per operator requirement 2578 */ getWlanRttOtherConfigs()2579 int[] getWlanRttOtherConfigs() { 2580 int[] pingConfigs = new int[5]; 2581 String[] rtt_ping_config = getWlanRttPingConfigs(); 2582 2583 if (rtt_ping_config != null && !rtt_ping_config[0].isEmpty()) { 2584 for (int i = 1; i < 6; i++) { 2585 if (rtt_ping_config[i] != null) { 2586 pingConfigs[i - 1] = Integer.parseInt(rtt_ping_config[i]); 2587 } 2588 } 2589 } 2590 return pingConfigs; 2591 } 2592 2593 /** 2594 * This method returns fallback Hysteresis timer on RTT Failure. 2595 * 2596 * @return : Based on carrier config settings as per operator requirement 2597 */ getWlanRttFallbackHystTimer()2598 int getWlanRttFallbackHystTimer() { 2599 String[] rtt_hyst_fallback_timer = getWlanRttPingConfigs(); 2600 2601 if (rtt_hyst_fallback_timer != null 2602 && !rtt_hyst_fallback_timer[0].isEmpty() 2603 && rtt_hyst_fallback_timer[6] != null) { 2604 return Integer.parseInt(rtt_hyst_fallback_timer[6]); 2605 } else { 2606 return 0; 2607 } 2608 } 2609 getWlanRttPingConfigs()2610 private String[] getWlanRttPingConfigs() { 2611 if (mWlanRttBackhaulCheckConfigsOnPing == null) return null; 2612 2613 return mWlanRttBackhaulCheckConfigsOnPing.split(","); 2614 } 2615 2616 /** 2617 * If fallback for Initial connection failure for the network capability is met is supported , 2618 * this method provides information about the failure retry count or retry timer or both if 2619 * supported until fallback to other transport. 2620 * 2621 * @param netCapability : (ims,sos,mms,xcap,cbs) 2622 * @return : 2623 * <NetworkCapability_SupportForFallback>:<retry_count>:<retry_timer>:<max_fallback_count> 2624 */ getInitialDataConnectionFallbackConfig(int netCapability)2625 int[] getInitialDataConnectionFallbackConfig(int netCapability) { 2626 2627 int[] fallbackConfigOnDataFail = new int[4]; 2628 String[] fallback_config = getFallbackConfigForNetCapability(netCapability); 2629 2630 if (fallback_config != null 2631 && fallback_config[0] != null 2632 && fallback_config[0].length() > 0) { 2633 // netCapability Availability Status 2634 fallbackConfigOnDataFail[0] = 1; 2635 2636 // Retry Count : && fallback_config[1].length() > 0 2637 if (fallback_config.length > 1 2638 && fallback_config[1] != null 2639 && !fallback_config[1].isEmpty()) { 2640 fallbackConfigOnDataFail[1] = Integer.parseInt(fallback_config[1]); 2641 } 2642 2643 // Retry timer 2644 if (fallback_config.length > 2 2645 && fallback_config[2] != null 2646 && !fallback_config[2].isEmpty()) { 2647 fallbackConfigOnDataFail[2] = Integer.parseInt(fallback_config[2]); 2648 } 2649 2650 // Max fallback count 2651 if (fallback_config.length > 4 2652 && fallback_config[4] != null 2653 && !fallback_config[4].isEmpty()) { 2654 fallbackConfigOnDataFail[3] = Integer.parseInt(fallback_config[4]); 2655 } 2656 } 2657 return fallbackConfigOnDataFail; 2658 } 2659 2660 /** 2661 * This method returns the fall back timer to be starting the restriction , for no. of retries 2662 * when met with the pdn fail fallback causes 2663 * 2664 * @param netCapability : (ims,sos,mms,xcap,cbs) 2665 * @return : Fallback Guard timer to be set on starting the fallback restrict @ RestrictManager 2666 */ getFallbackGuardTimerOnInitialConnectionFail(int netCapability)2667 int getFallbackGuardTimerOnInitialConnectionFail(int netCapability) { 2668 String[] fallback_guard_timer = getFallbackConfigForNetCapability(netCapability); 2669 2670 if (fallback_guard_timer != null 2671 && fallback_guard_timer[0] != null 2672 && fallback_guard_timer[0].length() > 0 2673 && ((fallback_guard_timer.length > 1 2674 && fallback_guard_timer[1] != null 2675 && !fallback_guard_timer[1].isEmpty()) 2676 || (fallback_guard_timer.length > 2 2677 && fallback_guard_timer[2] != null 2678 && !fallback_guard_timer[2].isEmpty())) 2679 && (fallback_guard_timer.length > 3 2680 && fallback_guard_timer[3] != null 2681 && !fallback_guard_timer[3].isEmpty())) { 2682 return Integer.parseInt(fallback_guard_timer[3]); 2683 } else { 2684 return 0; 2685 } 2686 } 2687 2688 /** 2689 * To support find the right Initial Pdn connection failure fallback config based on network 2690 * capability 2691 */ getFallbackConfigForNetCapability(int netCapability)2692 private String[] getFallbackConfigForNetCapability(int netCapability) { 2693 if (mFallbackOnInitialConnectionFailure != null 2694 && mFallbackOnInitialConnectionFailure.length > 0) { 2695 String netCapabilityName = QnsUtils.getNameOfNetCapability(netCapability); 2696 for (String config : mFallbackOnInitialConnectionFailure) { 2697 Log.d(mLogTag, "Fallback On Initial Failure enabled for " + config); 2698 if (config.contains(netCapabilityName)) { 2699 return config.split(":"); 2700 } 2701 } 2702 } 2703 return null; 2704 } 2705 2706 /** 2707 * Get the Sip Dialog Session policy when the Sip Dialog State is active. This Sip Dialog 2708 * Session policy is applied when there is no calling in the subscription, and when the device 2709 * is in a calling state, the calling policy is used first. 2710 * 2711 * @return 0: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_NONE} not Applied. The default value 2712 * for this key. 1: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VOICE_CALL} apply voice 2713 * call policy. 2: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VIDEO_CALL} apply video 2714 * call policy. 2715 */ getSipDialogSessionPolicy()2716 @QnsConstants.QnsSipDialogSessionPolicy int getSipDialogSessionPolicy() { 2717 return mSipDialogSessionPolicy; 2718 } 2719 2720 static class QnsConfigArray { 2721 2722 /* 2723 * static invalid 2724 */ 2725 static final int INVALID = 0x0000FFFF; 2726 /* 2727 * Thresholds, A signal value of good strength to enter. 2728 */ 2729 int mGood = INVALID; 2730 /* 2731 * Thresholds, A signal value of bad strength to leave. 2732 */ 2733 int mBad = INVALID; 2734 /* 2735 * Thresholds, A signal value of worst strength to enter. 2736 * The worst strength is only applicable for cellular. 2737 */ 2738 int mWorst = INVALID; 2739 QnsConfigArray(int good, int bad, int worst)2740 QnsConfigArray(int good, int bad, int worst) { 2741 set(good, bad, worst); 2742 } 2743 QnsConfigArray(int good, int bad)2744 QnsConfigArray(int good, int bad) { 2745 set(good, bad, INVALID); 2746 } 2747 set(int good, int bad, int worst)2748 void set(int good, int bad, int worst) { 2749 mGood = good; 2750 mBad = bad; 2751 mWorst = worst; 2752 } 2753 2754 @Override toString()2755 public String toString() { 2756 return "QnsConfigArray{" 2757 + "Good=" 2758 + mGood 2759 + ", Bad=" 2760 + mBad 2761 + ", Worst=" 2762 + mWorst 2763 + '}'; 2764 } 2765 } 2766 2767 @VisibleForTesting 2768 static class RtpMetricsConfig { 2769 /** Maximum jitter */ 2770 final int mJitter; 2771 2772 /** RTP packet loss rate in percentage */ 2773 final int mPktLossRate; 2774 2775 /** Time interval(milliseconds) of RTP packet loss rate */ 2776 final int mPktLossTime; 2777 2778 /** No RTP interval in milliseconds */ 2779 final int mNoRtpInterval; 2780 RtpMetricsConfig(int jitter, int pktLossRate, int pktLossTime, int noRtpInterval)2781 RtpMetricsConfig(int jitter, int pktLossRate, int pktLossTime, int noRtpInterval) { 2782 this.mJitter = jitter; 2783 this.mPktLossRate = pktLossRate; 2784 this.mPktLossTime = pktLossTime; 2785 this.mNoRtpInterval = noRtpInterval; 2786 } 2787 2788 @Override toString()2789 public String toString() { 2790 return "RtpMetricsConfig{" 2791 + "mJitter=" 2792 + mJitter 2793 + ", mPktLossRate=" 2794 + mPktLossRate 2795 + ", mPktLossTime=" 2796 + mPktLossTime 2797 + ", mNoRtpInterval=" 2798 + mNoRtpInterval 2799 + '}'; 2800 } 2801 } 2802 2803 @VisibleForTesting getQnsCarrierAnspSupportConfig()2804 QnsCarrierAnspSupportConfig getQnsCarrierAnspSupportConfig() { 2805 return mAnspConfigMgr; 2806 } 2807 } 2808