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.HashMap; 66 import java.util.HashSet; 67 import java.util.List; 68 import java.util.Locale; 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 static HashMap<Integer, String> sAccessNetworkMap = 686 new HashMap<>() { 687 { 688 put(AccessNetworkConstants.AccessNetworkType.EUTRAN, "eutran"); 689 put(AccessNetworkConstants.AccessNetworkType.UTRAN, "utran"); 690 put(AccessNetworkConstants.AccessNetworkType.NGRAN, "ngran"); 691 put(AccessNetworkConstants.AccessNetworkType.GERAN, "geran"); 692 put(AccessNetworkConstants.AccessNetworkType.IWLAN, "wifi"); 693 } 694 }; 695 696 static HashMap<Integer, String> sMeasTypeMap = 697 new HashMap<>() { 698 { 699 put(SIGNAL_MEASUREMENT_TYPE_RSRP, "rsrp"); 700 put(SIGNAL_MEASUREMENT_TYPE_RSRQ, "rsrq"); 701 put(SIGNAL_MEASUREMENT_TYPE_RSSNR, "rssnr"); 702 put(SIGNAL_MEASUREMENT_TYPE_SSRSRP, "ssrsrp"); 703 put(SIGNAL_MEASUREMENT_TYPE_SSRSRQ, "ssrsrq"); 704 put(SIGNAL_MEASUREMENT_TYPE_SSSINR, "sssinr"); 705 put(SIGNAL_MEASUREMENT_TYPE_RSCP, "rscp"); 706 put(SIGNAL_MEASUREMENT_TYPE_RSSI, "rssi"); 707 put(SIGNAL_MEASUREMENT_TYPE_ECNO, "ecno"); 708 } 709 }; 710 711 static HashMap<Integer, String> sCallTypeMap = 712 new HashMap<>() { 713 { 714 put(QnsConstants.CALL_TYPE_IDLE, "idle"); 715 put(QnsConstants.CALL_TYPE_VOICE, "voice"); 716 put(QnsConstants.CALL_TYPE_VIDEO, "video"); 717 } 718 }; 719 720 private final String mLogTag; 721 private final int mSlotIndex; 722 private final Context mContext; 723 private boolean mIsConfigLoaded = false; 724 protected int mSubId; 725 protected int mCurrCarrierId; 726 private final QnsEventDispatcher mQnsEventDispatcher; 727 private final QnsCarrierAnspSupportConfig mAnspConfigMgr; 728 @VisibleForTesting final Handler mHandler; 729 730 private boolean mIsWfcInAirplaneModeOnSupport; 731 private boolean mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported; 732 private boolean mIsHoGuardOnPreferenceSupport; 733 private boolean mIsServiceBarringCheckSupport; 734 private boolean mIsVideoOverIWLANWithCellularCheckSupport; 735 private boolean mIsRoveOutWifiBadGuardTimerConditionsSupported; 736 private boolean mIsAllowImsOverIwlanCellularLimitedCase; 737 private boolean mIsBlockIwlanInInternationalRoamWithoutWwan; 738 private boolean mIsBlockIpv6OnlyWifi; 739 private boolean mIsVolteRoamingSupported; 740 private final boolean[] mAnspSupportConfigArray = new boolean[3]; 741 742 private int mWifiThresBackHaulTimer; 743 private int mCellularThresBackHaulTimer; 744 private int mQnsImsTransportType; 745 private int mQnsSosTransportType; 746 private int mQnsMmsTransportType; 747 private int[] mQnsXcapSupportedAccessNetworkTypes; 748 private int mQnsCbsTransportType; 749 private int mXcapRatPreference; 750 private int mSosRatPreference; 751 private int mMmsRatPreference; 752 private int mCbsRatPreference; 753 private int mNetworkEnableHysteresisTimer; 754 private int mMinimumHandoverGuardingTimer; 755 private int mVowifiRegistrationTimerForVowifiActivation; 756 private int mSipDialogSessionPolicy; 757 758 private int[] mWwanHysteresisTimer; 759 private int[] mWlanHysteresisTimer; 760 private int[] mNonImsWwanHysteresisTimer; 761 private int[] mNonImsWlanHysteresisTimer; 762 private int[] mRTPMetricsData = new int[4]; 763 private int[] mWaitingTimerForPreferredTransport; 764 private int[] mAllowMaxIwlanHoCountOnReason; 765 private int[] mHoRestrictTimeOnRtpQuality; 766 private int[] mIsMmtelCapabilityRequired; 767 private int[] mIsWfcPreferredTransportRequired; 768 769 private String mWlanRttBackhaulCheckConfigsOnPing; 770 private String[] mImsAllowedRats; 771 private String[] mRoveInGuardTimerConditionThresholdGaps; 772 private String[] mFallbackOnInitialConnectionFailure; 773 private String[] mAccessNetworkMeasurementHysteresisDb; 774 775 @NonNull 776 private final List<FallbackRule> mFallbackWwanRuleWithImsUnregistered = new ArrayList<>(); 777 778 @NonNull 779 private final List<FallbackRule> mFallbackWwanRuleWithImsHoRegisterFail = new ArrayList<>(); 780 781 /** Rules for handover between IWLAN and cellular network. */ 782 @NonNull private List<HandoverRule> mHandoverRuleList = new ArrayList<>(); 783 784 protected QnsRegistrantList mQnsCarrierConfigLoadedRegistrants = new QnsRegistrantList(); 785 protected QnsRegistrantList mQnsCarrierConfigChangedRegistrants = new QnsRegistrantList(); 786 787 protected QnsProvisioningListener.QnsProvisioningInfo mQnsProvisioningInfo = 788 new QnsProvisioningListener.QnsProvisioningInfo(); 789 setQnsProvisioningInfo(QnsProvisioningListener.QnsProvisioningInfo info)790 void setQnsProvisioningInfo(QnsProvisioningListener.QnsProvisioningInfo info) { 791 mQnsProvisioningInfo = info; 792 } 793 applyProvisioningInfo( QnsConfigArray thresholds, int accessNetwork, int measurementType, int callType)794 private QnsConfigArray applyProvisioningInfo( 795 QnsConfigArray thresholds, int accessNetwork, int measurementType, int callType) { 796 797 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_1) 798 && thresholds.mBad != QnsConfigArray.INVALID 799 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 800 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 801 int bad = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_1); 802 Log.d(mLogTag, "provisioning bad THLTE1 old:" + thresholds.mBad + " new:" + bad); 803 thresholds.mBad = bad; 804 } 805 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_2) 806 && thresholds.mWorst != QnsConfigArray.INVALID 807 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 808 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 809 int worst = 810 mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_2); 811 Log.d(mLogTag, "provisioning worst THLTE2 old:" + thresholds.mWorst + " new:" + worst); 812 thresholds.mWorst = worst; 813 } 814 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_THRESHOLD_3) 815 && thresholds.mGood != QnsConfigArray.INVALID 816 && accessNetwork == AccessNetworkConstants.AccessNetworkType.EUTRAN 817 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSRP) { 818 int good = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_3); 819 Log.d(mLogTag, "provisioning good THLTE3 old:" + thresholds.mGood + " new:" + good); 820 thresholds.mGood = good; 821 } 822 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_THRESHOLD_A) 823 && thresholds.mGood != QnsConfigArray.INVALID 824 && accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 825 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSSI) { 826 int good = 827 mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_A); 828 Log.d(mLogTag, "provisioning good VOWT_A old:" + thresholds.mGood + " new:" + good); 829 thresholds.mGood = good; 830 } 831 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_THRESHOLD_B) 832 && thresholds.mBad != QnsConfigArray.INVALID 833 && accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 834 && measurementType == SIGNAL_MEASUREMENT_TYPE_RSSI) { 835 int bad = mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_B); 836 Log.d(mLogTag, "provisioning bad VOWT_B old:" + thresholds.mBad + " new:" + bad); 837 thresholds.mBad = bad; 838 // TODO : make video threshold gap config, and move in getThreshold...() 839 if (getCarrierId() == 1839 && callType == QnsConstants.CALL_TYPE_VIDEO) { 840 thresholds.mBad = bad + 5; 841 } 842 } 843 844 return thresholds; 845 } 846 847 static class FallbackRule { 848 /** Key : IMS registration fail reason, value : fallback time in millis */ 849 final Set<Integer> mReasons; 850 851 final int mBackoffTimeMillis; 852 final int mPreferenceMode; 853 FallbackRule(Set<Integer> reasons, int backoffTimeMillis, int preferenceMode)854 FallbackRule(Set<Integer> reasons, int backoffTimeMillis, int preferenceMode) { 855 mReasons = reasons; 856 mBackoffTimeMillis = backoffTimeMillis; 857 mPreferenceMode = preferenceMode; 858 } 859 getFallBackTime(int reason)860 int getFallBackTime(int reason) { 861 if (mReasons.contains(reason)) { 862 return mBackoffTimeMillis; 863 } else { 864 return 0; 865 } 866 } 867 868 @Override toString()869 public String toString() { 870 StringBuilder builder = new StringBuilder(); 871 builder.append("FallbackRule time:").append(mBackoffTimeMillis); 872 if (mPreferenceMode == -1) { 873 builder.append(" "); 874 } else if (mPreferenceMode == QnsConstants.CELL_PREF) { 875 builder.append(" " + "CELL_PREF_MODE"); 876 } else if (mPreferenceMode == QnsConstants.WIFI_PREF) { 877 builder.append(" " + "WIFI_PREF_MODE"); 878 } 879 builder.append(" reasons:"); 880 for (Integer i : mReasons) { 881 builder.append(i).append(" "); 882 } 883 return builder.toString(); 884 } 885 } 886 887 static class HandoverRule { 888 @Retention(RetentionPolicy.SOURCE) 889 @IntDef( 890 prefix = {"RULE_TYPE_"}, 891 value = { 892 RULE_TYPE_ALLOWED, 893 RULE_TYPE_DISALLOWED, 894 }) 895 @interface HandoverRuleType {} 896 897 /** Indicating this rule is for allowing handover. */ 898 static final int RULE_TYPE_ALLOWED = 1; 899 900 /** Indicating this rule is for disallowing handover. */ 901 static final int RULE_TYPE_DISALLOWED = 2; 902 903 private static final String RULE_TAG_SOURCE_ACCESS_NETWORKS = "source"; 904 905 private static final String RULE_TAG_TARGET_ACCESS_NETWORKS = "target"; 906 907 private static final String RULE_TAG_TYPE = "type"; 908 909 private static final String RULE_TAG_CAPABILITIES = "capabilities"; 910 911 private static final String RULE_TAG_ROAMING = "roaming"; 912 913 /** Handover rule type. */ 914 @HandoverRuleType final int mHandoverRuleType; 915 916 /** The applicable source access networks for handover. */ 917 @NonNull @AccessNetworkConstants.RadioAccessNetworkType 918 final Set<Integer> mSourceAccessNetworks; 919 920 /** The applicable target access networks for handover. */ 921 @NonNull @AccessNetworkConstants.RadioAccessNetworkType 922 final Set<Integer> mTargetAccessNetworks; 923 924 /** 925 * The network capabilities to any of which this handover rule applies. If is empty, then 926 * capability is ignored as a rule matcher. 927 */ 928 @NonNull @NetCapability final Set<Integer> mNetworkCapabilities; 929 930 /** {@code true} indicates this policy is only applicable when the device is roaming. */ 931 final boolean mIsOnlyForRoaming; 932 933 /** 934 * Constructor 935 * 936 * @param ruleString The rule in string format. 937 * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY 938 */ HandoverRule(@onNull String ruleString)939 HandoverRule(@NonNull String ruleString) { 940 if (TextUtils.isEmpty(ruleString)) { 941 throw new IllegalArgumentException("illegal rule " + ruleString); 942 } 943 944 Set<Integer> source = null, target = null, capabilities = Collections.emptySet(); 945 int type = 0; 946 boolean roaming = false; 947 948 ruleString = ruleString.trim().toLowerCase(Locale.ROOT); 949 String[] expressions = ruleString.split("\\s*,\\s*"); 950 for (String expression : expressions) { 951 String[] tokens = expression.trim().split("\\s*=\\s*"); 952 if (tokens.length != 2) { 953 throw new IllegalArgumentException( 954 "illegal rule " + ruleString + ", tokens=" + Arrays.toString(tokens)); 955 } 956 String key = tokens[0].trim(); 957 String value = tokens[1].trim(); 958 try { 959 switch (key) { 960 case RULE_TAG_SOURCE_ACCESS_NETWORKS: 961 source = 962 Arrays.stream(value.split("\\s*\\|\\s*")) 963 .map(String::trim) 964 .map(QnsConstants::accessNetworkTypeFromString) 965 .collect(Collectors.toSet()); 966 break; 967 case RULE_TAG_TARGET_ACCESS_NETWORKS: 968 target = 969 Arrays.stream(value.split("\\s*\\|\\s*")) 970 .map(String::trim) 971 .map(QnsConstants::accessNetworkTypeFromString) 972 .collect(Collectors.toSet()); 973 break; 974 case RULE_TAG_TYPE: 975 if (value.toLowerCase(Locale.ROOT).equals("allowed")) { 976 type = RULE_TYPE_ALLOWED; 977 } else if (value.toLowerCase(Locale.ROOT).equals("disallowed")) { 978 type = RULE_TYPE_DISALLOWED; 979 } else { 980 throw new IllegalArgumentException("unexpected rule type " + value); 981 } 982 break; 983 case RULE_TAG_CAPABILITIES: 984 capabilities = QnsUtils.getNetworkCapabilitiesFromString(value); 985 break; 986 case RULE_TAG_ROAMING: 987 roaming = Boolean.parseBoolean(value); 988 break; 989 default: 990 throw new IllegalArgumentException("unexpected key " + key); 991 } 992 } catch (Exception e) { 993 e.printStackTrace(); 994 throw new IllegalArgumentException( 995 "illegal rule \"" + ruleString + "\", e=" + e); 996 } 997 } 998 999 if (source == null || target == null || source.isEmpty() || target.isEmpty()) { 1000 throw new IllegalArgumentException( 1001 "Need to specify both source and target. " + "\"" + ruleString + "\""); 1002 } 1003 1004 if (source.contains(AccessNetworkConstants.AccessNetworkType.UNKNOWN) 1005 && type != RULE_TYPE_DISALLOWED) { 1006 throw new IllegalArgumentException("Unknown access network can be only specified in" 1007 + " the disallowed rule. \"" + ruleString + "\""); 1008 } 1009 1010 if (target.contains(AccessNetworkConstants.AccessNetworkType.UNKNOWN)) { 1011 throw new IllegalArgumentException( 1012 "Target access networks contains unknown. " + "\"" + ruleString + "\""); 1013 } 1014 1015 if (type == 0) { 1016 throw new IllegalArgumentException( 1017 "Rule type is not specified correctly. " + "\"" + ruleString + "\""); 1018 } 1019 1020 if (capabilities != null && capabilities.contains(-1)) { 1021 throw new IllegalArgumentException( 1022 "Network capabilities contains unknown. " + "\"" + ruleString + "\""); 1023 } 1024 1025 if (!source.contains(AccessNetworkConstants.AccessNetworkType.IWLAN) 1026 && !target.contains(AccessNetworkConstants.AccessNetworkType.IWLAN)) { 1027 throw new IllegalArgumentException( 1028 "IWLAN must be specified in either source or " 1029 + "target access networks.\"" 1030 + ruleString 1031 + "\""); 1032 } 1033 1034 mSourceAccessNetworks = source; 1035 mTargetAccessNetworks = target; 1036 this.mHandoverRuleType = type; 1037 mNetworkCapabilities = capabilities; 1038 mIsOnlyForRoaming = roaming; 1039 } 1040 1041 @Override toString()1042 public String toString() { 1043 return "[HandoverRule: type=" 1044 + (mHandoverRuleType == RULE_TYPE_ALLOWED ? "allowed" : "disallowed") 1045 + ", source=" 1046 + mSourceAccessNetworks.stream() 1047 .map(QnsConstants::accessNetworkTypeToString) 1048 .collect(Collectors.joining("|")) 1049 + ", target=" 1050 + mTargetAccessNetworks.stream() 1051 .map(QnsConstants::accessNetworkTypeToString) 1052 .collect(Collectors.joining("|")) 1053 + ", isRoaming=" 1054 + mIsOnlyForRoaming 1055 + ", capabilities=" 1056 + QnsUtils.networkCapabilitiesToString(mNetworkCapabilities) 1057 + "]"; 1058 } 1059 } 1060 1061 private class QnsCarrierConfigChangeHandler extends Handler { QnsCarrierConfigChangeHandler(Looper looper)1062 QnsCarrierConfigChangeHandler(Looper looper) { 1063 super(looper); 1064 } 1065 1066 @Override handleMessage(Message message)1067 public void handleMessage(Message message) { 1068 switch (message.what) { 1069 case QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED: 1070 Log.d(mLogTag, "Event received QNS_EVENT_CARRIER_CONFIG_CHANGED"); 1071 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1072 int newCarrierID = getCarrierId(); 1073 Log.d( 1074 mLogTag, 1075 "Carrier Id: current=" + mCurrCarrierId + ", new=" + newCarrierID); 1076 if (newCarrierID != 0 && newCarrierID != UNKNOWN_CARRIER_ID) { 1077 if (mCurrCarrierId != newCarrierID) { 1078 mCurrCarrierId = newCarrierID; 1079 loadQnsConfigurations(); 1080 mIsConfigLoaded = true; 1081 notifyLoadQnsConfigurationsCompleted(); 1082 } else { 1083 if (isQnsConfigChanged()) { 1084 Log.d(mLogTag, "Qns Carrier config updated found"); 1085 notifyQnsConfigurationsChanged(); 1086 } 1087 } 1088 } 1089 } 1090 break; 1091 default: 1092 break; 1093 } 1094 } 1095 } 1096 1097 /** 1098 * Constructor to Initial Slot and Context whose carrier config ID needs to be loaded along with 1099 * initialising the Action Intent on which Carrier Config ID to be loaded. 1100 */ QnsCarrierConfigManager(Context context, QnsEventDispatcher dispatcher, int slotIndex)1101 QnsCarrierConfigManager(Context context, QnsEventDispatcher dispatcher, int slotIndex) { 1102 mSlotIndex = slotIndex; 1103 mContext = context; 1104 mLogTag = 1105 QnsConstants.QNS_TAG 1106 + "_" 1107 + QnsCarrierConfigManager.class.getSimpleName() 1108 + "_" 1109 + mSlotIndex; 1110 mQnsEventDispatcher = dispatcher; 1111 mAnspConfigMgr = new QnsCarrierAnspSupportConfig(slotIndex); 1112 1113 HandlerThread handlerThread = new HandlerThread(mLogTag); 1114 handlerThread.start(); 1115 mHandler = 1116 new QnsCarrierConfigManager.QnsCarrierConfigChangeHandler( 1117 handlerThread.getLooper()); 1118 1119 List<Integer> events = new ArrayList<>(); 1120 events.add(QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED); 1121 mQnsEventDispatcher.registerEvent(events, mHandler); 1122 1123 // sending empty message when new object created; as actual event will not be received in 1124 // case QNS restarts. 1125 // This EVENT will not be processed in bootup case since carrier id will be invalid until 1126 // actual event received from QnsEventDispatcher. 1127 mHandler.sendEmptyMessage(QnsEventDispatcher.QNS_EVENT_CARRIER_CONFIG_CHANGED); 1128 1129 // To do : Update based on xml version Changes handling 1130 // To do : Operator Update on Threshold changes handling 1131 } 1132 1133 /** Below API clears the current Access Network selection Policies */ close()1134 void close() { 1135 if (mHandler != null) mQnsEventDispatcher.unregisterEvent(mHandler); 1136 } 1137 readFromCarrierConfigManager(Context context)1138 synchronized PersistableBundle readFromCarrierConfigManager(Context context) { 1139 PersistableBundle carrierConfigBundle; 1140 CarrierConfigManager carrierConfigManager = 1141 context.getSystemService(CarrierConfigManager.class); 1142 1143 if (carrierConfigManager == null) { 1144 throw new IllegalStateException("Carrier config manager is null."); 1145 } 1146 carrierConfigBundle = carrierConfigManager.getConfigForSubId(getSubId()); 1147 1148 return carrierConfigBundle; 1149 } 1150 readFromAssets(Context context)1151 synchronized PersistableBundle readFromAssets(Context context) { 1152 PersistableBundle assetBundle; 1153 1154 assetBundle = QnsUtils.readQnsDefaultConfigFromAssets(context, mCurrCarrierId); 1155 1156 if (assetBundle == null) { 1157 throw new IllegalStateException("Carrier config manager is null."); 1158 } 1159 1160 return assetBundle; 1161 } 1162 1163 /** Below API is used for Loading the carrier configurations based on Current Carrier ID */ loadQnsConfigurations()1164 void loadQnsConfigurations() { 1165 1166 PersistableBundle carrierConfigBundle = readFromCarrierConfigManager(mContext); 1167 Log.d(mLogTag, "CarrierConfig Bundle for Slot: " + mSlotIndex + carrierConfigBundle); 1168 1169 PersistableBundle assetConfigBundle = readFromAssets(mContext); 1170 Log.d(mLogTag, "AssetConfig Bundle for Slot: " + mSlotIndex + assetConfigBundle); 1171 1172 // load configurations supporting ANE 1173 loadQnsAneSupportConfigurations(carrierConfigBundle, assetConfigBundle); 1174 1175 // load qns Ansp (Access Network Selection Policy) carrier Support Configurations 1176 // for building Internal ANSP Policies 1177 loadAnspCarrierSupportConfigs(carrierConfigBundle, assetConfigBundle); 1178 1179 mAnspConfigMgr.loadQnsAnspSupportArray(carrierConfigBundle, assetConfigBundle); 1180 1181 // Load configs using Carrier Config Manager Keys 1182 loadDirectFromCarrierConfigManagerKey(carrierConfigBundle); 1183 1184 loadWfcConfigurations(carrierConfigBundle, assetConfigBundle); 1185 1186 loadMediaThreshold(carrierConfigBundle, assetConfigBundle); 1187 } 1188 1189 /** 1190 * Below API takes care of loading the configuration based on the carrier config Manager 1191 * available for given carrier config manager keys. 1192 */ loadDirectFromCarrierConfigManagerKey(PersistableBundle bundleCarrier)1193 void loadDirectFromCarrierConfigManagerKey(PersistableBundle bundleCarrier) { 1194 loadHandoverRules( 1195 bundleCarrier, null, CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY); 1196 loadCarrierConfig(bundleCarrier); 1197 } 1198 1199 /** 1200 * Below API takes care of validating the configs (Threshold & HO rules) Updates after loading 1201 * Qns configurations, for the current operator in use, in case of config update scenario 1202 * 1203 * @return : true/false 1204 */ isQnsConfigChanged()1205 synchronized boolean isQnsConfigChanged() { 1206 PersistableBundle carrierConfigBundle = readFromCarrierConfigManager(mContext); 1207 Log.d( 1208 mLogTag, 1209 "Check carrier config for Qns item changefor_slot: " 1210 + mSlotIndex 1211 + "_" 1212 + carrierConfigBundle); 1213 PersistableBundle assetConfigBundle = readFromAssets(mContext); 1214 Log.d( 1215 mLogTag, 1216 "Check Asset config for Qns item changefor_slot: " 1217 + mSlotIndex 1218 + "_" 1219 + assetConfigBundle); 1220 1221 boolean isThresholdConfigChanged = 1222 checkThresholdConfigChange(carrierConfigBundle, assetConfigBundle); 1223 boolean isHandoverRulesChanged = 1224 checkHandoverRuleConfigChange( 1225 carrierConfigBundle, 1226 null, 1227 CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY); 1228 Log.d( 1229 mLogTag, 1230 "Threshold config changed = " 1231 + isThresholdConfigChanged 1232 + ", IMS handover rule changed = " 1233 + isHandoverRulesChanged); 1234 1235 return (isThresholdConfigChanged || isHandoverRulesChanged); 1236 } 1237 1238 /** 1239 * Below API takes to check if current HO rules as any difference with existing HO rules Updated 1240 * based on Event Carrier config change event received after initial loading @Param 1241 * PersistableBundle : configBundle 1242 * 1243 * @return true/false 1244 */ checkHandoverRuleConfigChange( PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle, String key)1245 synchronized boolean checkHandoverRuleConfigChange( 1246 PersistableBundle carrierConfigBundle, 1247 PersistableBundle assetConfigBundle, 1248 String key) { 1249 List<HandoverRule> handoverUpdateRuleList = 1250 updateHandoverRules(carrierConfigBundle, assetConfigBundle, key); 1251 1252 Log.d(mLogTag, "New rule:" + handoverUpdateRuleList.toString()); 1253 Log.d(mLogTag, "Existing rule:" + mHandoverRuleList.toString()); 1254 1255 if (mHandoverRuleList.toString().equals(handoverUpdateRuleList.toString()) 1256 || handoverUpdateRuleList.isEmpty() 1257 || mHandoverRuleList.isEmpty()) { 1258 handoverUpdateRuleList.clear(); 1259 return false; 1260 } else { 1261 mHandoverRuleList = new ArrayList<>(handoverUpdateRuleList); 1262 Log.d(mLogTag, "New rule Updated:" + mHandoverRuleList); 1263 handoverUpdateRuleList.clear(); 1264 return true; 1265 } 1266 } 1267 1268 /** 1269 * Below API takes to check if ANSP threshold configs was Updated based on Event Carrier config 1270 * change event received after initial Qns configuration loading is completed 1271 */ checkThresholdConfigChange( PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle)1272 synchronized boolean checkThresholdConfigChange( 1273 PersistableBundle carrierConfigBundle, PersistableBundle assetConfigBundle) { 1274 1275 return mAnspConfigMgr.checkQnsAnspConfigChange(carrierConfigBundle, assetConfigBundle); 1276 } 1277 1278 /** 1279 * Below API takes care of loading the configuration based on the Bundle data built based on 1280 * asset folder xml file . (Except reading Key item of threshold & ANSP 1281 */ loadQnsAneSupportConfigurations( PersistableBundle bundleCarrier, PersistableBundle bundleAsset)1282 void loadQnsAneSupportConfigurations( 1283 PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 1284 1285 mIsWfcInAirplaneModeOnSupport = 1286 getConfig( 1287 bundleCarrier, bundleAsset, KEY_QNS_SUPPORT_WFC_DURING_AIRPLANE_MODE_BOOL); 1288 mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported = 1289 getConfig( 1290 bundleCarrier, 1291 bundleAsset, 1292 KEY_IN_CALL_HO_DECISION_WLAN_TO_WWAN_WITHOUT_VOPS_CONDITION_BOOL); 1293 mIsHoGuardOnPreferenceSupport = 1294 getConfig(bundleCarrier, bundleAsset, KEY_QNS_HO_GUARDING_BY_PREFERENCE_BOOL); 1295 mIsServiceBarringCheckSupport = 1296 getConfig(bundleCarrier, bundleAsset, KEY_QNS_SUPPORT_SERVICE_BARRING_CHECK_BOOL); 1297 mIsVideoOverIWLANWithCellularCheckSupport = 1298 getConfig( 1299 bundleCarrier, 1300 bundleAsset, 1301 KEY_QNS_ALLOW_VIDEO_OVER_IWLAN_WITH_CELLULAR_LIMITED_CASE_BOOL); 1302 mIsRoveOutWifiBadGuardTimerConditionsSupported = 1303 getConfig( 1304 bundleCarrier, 1305 bundleAsset, 1306 KEY_QNS_ROVE_OUT_POLICY_WITH_WIFI_BAD_GUARDTIMER_CONDITIONS_BOOL); 1307 mIsAllowImsOverIwlanCellularLimitedCase = 1308 getConfig( 1309 bundleCarrier, 1310 bundleAsset, 1311 KEY_QNS_ALLOW_IMS_OVER_IWLAN_CELLULAR_LIMITED_CASE_BOOL); 1312 mIsBlockIwlanInInternationalRoamWithoutWwan = 1313 getConfig( 1314 bundleCarrier, 1315 bundleAsset, 1316 KEY_BLOCK_IWLAN_IN_INTERNATIONAL_ROAMING_WITHOUT_WWAN_BOOL); 1317 mIsBlockIpv6OnlyWifi = getConfig(bundleCarrier, bundleAsset, KEY_BLOCK_IPV6_ONLY_WIFI_BOOL); 1318 1319 mWifiThresBackHaulTimer = 1320 getConfig( 1321 bundleCarrier, 1322 bundleAsset, 1323 KEY_QNS_WIFI_RSSI_THRESHOLDBACKHAUL_TIMER_MS_INT); 1324 mCellularThresBackHaulTimer = 1325 getConfig( 1326 bundleCarrier, 1327 bundleAsset, 1328 KEY_QNS_CELLULAR_SS_THRESHOLDBACKHAUL_TIMER_MS_INT); 1329 mQnsImsTransportType = 1330 getConfig(bundleCarrier, bundleAsset, KEY_QNS_IMS_TRANSPORT_TYPE_INT); 1331 mQnsSosTransportType = 1332 getConfig(bundleCarrier, bundleAsset, KEY_QNS_SOS_TRANSPORT_TYPE_INT); 1333 mQnsMmsTransportType = 1334 getConfig(bundleCarrier, bundleAsset, KEY_QNS_MMS_TRANSPORT_TYPE_INT); 1335 mQnsXcapSupportedAccessNetworkTypes = 1336 getConfig( 1337 bundleCarrier, 1338 bundleAsset, 1339 CarrierConfigManager.ImsSs.KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY); 1340 mQnsCbsTransportType = 1341 getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_TRANSPORT_TYPE_INT); 1342 mQnsCbsTransportType = 1343 getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_TRANSPORT_TYPE_INT); 1344 mXcapRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_XCAP_RAT_PREFERENCE_INT); 1345 mSosRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_SOS_RAT_PREFERENCE_INT); 1346 mMmsRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_MMS_RAT_PREFERENCE_INT); 1347 mCbsRatPreference = getConfig(bundleCarrier, bundleAsset, KEY_QNS_CBS_RAT_PREFERENCE_INT); 1348 mNetworkEnableHysteresisTimer = 1349 getConfig( 1350 bundleCarrier, 1351 bundleAsset, 1352 KEY_QNS_IMS_NETWORK_ENABLE_HO_HYSTERESIS_TIMER_INT); 1353 1354 mWwanHysteresisTimer = 1355 getConfig(bundleCarrier, bundleAsset, KEY_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1356 mWlanHysteresisTimer = 1357 getConfig(bundleCarrier, bundleAsset, KEY_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1358 mNonImsWwanHysteresisTimer = 1359 getConfig( 1360 bundleCarrier, bundleAsset, KEY_NON_IMS_WWAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1361 mNonImsWlanHysteresisTimer = 1362 getConfig( 1363 bundleCarrier, bundleAsset, KEY_NON_IMS_WLAN_HYSTERESIS_TIMER_MS_INT_ARRAY); 1364 mMinimumHandoverGuardingTimer = 1365 getConfig(bundleCarrier, bundleAsset, KEY_MINIMUM_HANDOVER_GUARDING_TIMER_MS_INT); 1366 mWaitingTimerForPreferredTransport = 1367 getConfig( 1368 bundleCarrier, 1369 bundleAsset, 1370 KEY_WAITING_TIME_FOR_PREFERRED_TRANSPORT_WHEN_POWER_ON_INT_ARRAY); 1371 mAllowMaxIwlanHoCountOnReason = 1372 getConfig( 1373 bundleCarrier, 1374 bundleAsset, 1375 KEY_QNS_IN_CALL_ROVEIN_ALLOWED_COUNT_AND_FALLBACK_REASON_INT_ARRAY); 1376 mHoRestrictTimeOnRtpQuality = 1377 getConfig( 1378 bundleCarrier, 1379 bundleAsset, 1380 KEY_QNS_HO_RESTRICT_TIME_WITH_LOW_RTP_QUALITY_MILLIS_INT_ARRAY); 1381 mWlanRttBackhaulCheckConfigsOnPing = 1382 getConfig( 1383 bundleCarrier, 1384 bundleAsset, 1385 KEY_QNS_WLAN_RTT_BACKHAUL_CHECK_ON_ICMP_PING_STRING); 1386 1387 mFallbackOnInitialConnectionFailure = 1388 getConfig( 1389 bundleCarrier, 1390 bundleAsset, 1391 KEY_QNS_FALLBACK_ON_INITIAL_CONNECTION_FAILURE_STRING_ARRAY); 1392 mImsAllowedRats = 1393 getConfig(bundleCarrier, bundleAsset, KEY_IMS_CELLULAR_ALLOWED_RAT_STRING_ARRAY); 1394 mRoveInGuardTimerConditionThresholdGaps = 1395 getConfig( 1396 bundleCarrier, 1397 bundleAsset, 1398 KEY_QNS_ROVEIN_THRESHOLD_GAP_WITH_GUARD_TIMER_STRING_ARRAY); 1399 mSipDialogSessionPolicy = 1400 getConfig(bundleCarrier, bundleAsset, KEY_SIP_DIALOG_SESSION_POLICY_INT); 1401 mAccessNetworkMeasurementHysteresisDb = 1402 getConfig( 1403 bundleCarrier, 1404 bundleAsset, 1405 KEY_QNS_CELLULAR_SIGNAL_STRENGTH_HYSTERESIS_DB_STRING_ARRAY); 1406 1407 loadFallbackPolicyWithImsRegiFail(bundleCarrier, bundleAsset); 1408 } 1409 1410 @VisibleForTesting loadWfcConfigurations(PersistableBundle bundleCarrier, PersistableBundle bundleAsset)1411 void loadWfcConfigurations(PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 1412 1413 mVowifiRegistrationTimerForVowifiActivation = 1414 getConfig( 1415 bundleCarrier, 1416 bundleAsset, 1417 KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT); 1418 } 1419 1420 @VisibleForTesting loadFallbackPolicyWithImsRegiFail(PersistableBundle carrier, PersistableBundle asset)1421 void loadFallbackPolicyWithImsRegiFail(PersistableBundle carrier, PersistableBundle asset) { 1422 synchronized (this) { 1423 mFallbackWwanRuleWithImsUnregistered.clear(); 1424 String[] fallbackRulesStrings = 1425 getConfig( 1426 carrier, 1427 asset, 1428 KEY_QNS_FALLBACK_WWAN_IMS_UNREGISTRATION_REASON_STRING_ARRAY); 1429 if (fallbackRulesStrings != null) { 1430 Log.d(mLogTag, "loadFallbackPolicyWithImsRegiFail" + fallbackRulesStrings.length); 1431 for (String ruleString : fallbackRulesStrings) { 1432 Log.d(mLogTag, " ruleString1:" + ruleString); 1433 FallbackRule rule = parseFallbackRule(ruleString); 1434 if (rule != null) { 1435 mFallbackWwanRuleWithImsUnregistered.add(rule); 1436 } 1437 } 1438 } else { 1439 Log.d(mLogTag, "Config FallbackWwanRuleWithImsUnregistered is null"); 1440 } 1441 mFallbackWwanRuleWithImsHoRegisterFail.clear(); 1442 fallbackRulesStrings = 1443 getConfig( 1444 carrier, 1445 asset, 1446 KEY_QNS_FALLBACK_WWAN_IMS_HO_REGISTER_FAIL_REASON_STRING_ARRAY); 1447 if (fallbackRulesStrings != null) { 1448 Log.d(mLogTag, "loadFallbackPolicyWithImsRegiFail2:" + fallbackRulesStrings.length); 1449 for (String ruleString : fallbackRulesStrings) { 1450 Log.d(mLogTag, " ruleString2:" + ruleString); 1451 FallbackRule rule = parseFallbackRule(ruleString); 1452 if (rule != null) { 1453 mFallbackWwanRuleWithImsHoRegisterFail.add(rule); 1454 } 1455 } 1456 } else { 1457 Log.d(mLogTag, "Config mFallbackWwanRuleWithImsHoRegisterFail is null"); 1458 } 1459 } 1460 } 1461 parseFallbackRule(String ruleString)1462 private FallbackRule parseFallbackRule(String ruleString) { 1463 if (TextUtils.isEmpty(ruleString)) { 1464 throw new IllegalArgumentException("illegal rule " + ruleString); 1465 } 1466 Set<Integer> reasons = new ArraySet<>(); 1467 int time = 0; 1468 int preferenceMode = -1; 1469 ruleString = ruleString.trim().toLowerCase(Locale.ROOT); 1470 String[] expressions = ruleString.split("\\s*,\\s*"); 1471 for (String expression : expressions) { 1472 String[] tokens = expression.trim().split("\\s*=\\s*"); 1473 if (tokens.length != 2) { 1474 throw new IllegalArgumentException( 1475 "illegal rule " + ruleString + ", tokens=" + Arrays.toString(tokens)); 1476 } 1477 String key = tokens[0].trim(); 1478 String value = tokens[1].trim(); 1479 1480 try { 1481 switch (key) { 1482 case "cause": 1483 String[] cause = value.trim().split("\\s*\\|\\s*"); 1484 for (String c : cause) { 1485 if (!c.contains("~")) { 1486 reasons.add(Integer.parseInt(c)); 1487 } else { 1488 String[] tok = c.trim().split("\\s*~\\s*"); 1489 int start = Integer.parseInt(tok[0]); 1490 int end = Integer.parseInt(tok[1]); 1491 for (int i = start; i <= end; i++) { 1492 reasons.add(i); 1493 } 1494 } 1495 } 1496 break; 1497 case "time": 1498 time = Integer.parseInt(value); 1499 break; 1500 case "preference": 1501 if (value.equals("cell")) { 1502 preferenceMode = QnsConstants.CELL_PREF; 1503 } else if (value.equals("wifi")) { 1504 preferenceMode = QnsConstants.WIFI_PREF; 1505 } 1506 break; 1507 1508 default: 1509 throw new IllegalArgumentException("unexpected key " + key); 1510 } 1511 1512 } catch (Exception e) { 1513 e.printStackTrace(); 1514 throw new IllegalArgumentException("illegal rule \"" + ruleString + "\", e=" + e); 1515 } 1516 } 1517 if (reasons.size() > 0) { 1518 return new FallbackRule(reasons, time, preferenceMode); 1519 } else { 1520 return null; 1521 } 1522 } 1523 getConfig( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String configKey)1524 private synchronized <T> T getConfig( 1525 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String configKey) { 1526 return QnsUtils.getConfig(bundleCarrier, bundleAsset, configKey); 1527 } 1528 1529 /** Load handover rules from carrier config. */ 1530 @VisibleForTesting loadHandoverRules( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key)1531 void loadHandoverRules( 1532 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key) { 1533 synchronized (this) { 1534 mHandoverRuleList.clear(); 1535 String[] handoverRulesStrings = getConfig(bundleCarrier, bundleAsset, key); 1536 if (handoverRulesStrings != null) { 1537 for (String ruleString : handoverRulesStrings) { 1538 Log.d(mLogTag, "loadHandoverRules: " + ruleString); 1539 try { 1540 mHandoverRuleList.add(new HandoverRule(ruleString)); 1541 } catch (IllegalArgumentException e) { 1542 Log.d(mLogTag, "loadHandoverRules: " + e.getMessage()); 1543 } 1544 } 1545 } 1546 } 1547 } 1548 loadMediaThreshold(PersistableBundle bundleCarrier, PersistableBundle assetConfigBundle)1549 void loadMediaThreshold(PersistableBundle bundleCarrier, PersistableBundle assetConfigBundle) { 1550 //read Jitter 1551 mRTPMetricsData[0] = getConfig( 1552 bundleCarrier, null, 1553 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_JITTER_THRESHOLD_MILLIS_INT); 1554 //read Packet Loss Rate 1555 mRTPMetricsData[1] = getConfig( 1556 bundleCarrier, null, 1557 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT); 1558 //read Inactivity Time 1559 long inactivityTime = getConfig( 1560 bundleCarrier, null, 1561 CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG); 1562 mRTPMetricsData[3] = (int) inactivityTime; 1563 //read Packet Loss Duration 1564 mRTPMetricsData[2] = getConfig( 1565 bundleCarrier, assetConfigBundle, 1566 KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT); 1567 } 1568 1569 /** Updated handover rules from carrier config. */ 1570 @VisibleForTesting updateHandoverRules( PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key)1571 List<HandoverRule> updateHandoverRules( 1572 PersistableBundle bundleCarrier, PersistableBundle bundleAsset, String key) { 1573 List<HandoverRule> readNewHandoverRuleList = new ArrayList<>(); 1574 synchronized (this) { 1575 String[] handoverRulesStrings = getConfig(bundleCarrier, bundleAsset, key); 1576 if (handoverRulesStrings != null) { 1577 for (String ruleString : handoverRulesStrings) { 1578 Log.d(mLogTag, "UpdateHandoverRules: " + ruleString); 1579 try { 1580 Log.d(mLogTag, "Rule Updated"); 1581 readNewHandoverRuleList.add(new HandoverRule(ruleString)); 1582 } catch (IllegalArgumentException e) { 1583 Log.d(mLogTag, "UpdateHandoverRules: " + e.getMessage()); 1584 } 1585 } 1586 } 1587 } 1588 return readNewHandoverRuleList; 1589 } 1590 1591 /** Load carrier config. */ 1592 @VisibleForTesting loadCarrierConfig(PersistableBundle bundleCarrier)1593 void loadCarrierConfig(PersistableBundle bundleCarrier) { 1594 mIsMmtelCapabilityRequired = 1595 getConfig( 1596 bundleCarrier, 1597 null, 1598 CarrierConfigManager.Ims.KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY); 1599 mIsVolteRoamingSupported = 1600 getConfig( 1601 bundleCarrier, 1602 null, 1603 CarrierConfigManager.ImsVoice.KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL); 1604 } 1605 1606 /** 1607 * To read the current Carrier ID based on the Slot ID and Context info 1608 * 1609 * @return : Current Carrier ID 1610 */ getCarrierId()1611 int getCarrierId() { 1612 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1613 if (tm != null) { 1614 tm = tm.createForSubscriptionId(QnsUtils.getSubId(mContext, mSlotIndex)); 1615 return tm.getSimCarrierId(); 1616 } 1617 return 0; 1618 } 1619 1620 /** 1621 * To read the current Subscription ID based on the Slot ID and Context info Output : Current 1622 * Carrier ID 1623 */ getSubId()1624 int getSubId() { 1625 mSubId = QnsUtils.getSubId(mContext, mSlotIndex); 1626 return mSubId; 1627 } 1628 1629 /** Notify all the registrants of the Slot loaded after carrier config loading is Completed */ notifyLoadQnsConfigurationsCompleted()1630 protected void notifyLoadQnsConfigurationsCompleted() { 1631 if (mQnsCarrierConfigLoadedRegistrants != null) { 1632 mQnsCarrierConfigLoadedRegistrants.notifyRegistrants(); 1633 } else { 1634 Log.d(mLogTag, "notifyLoadQnsConfigurationsCompleted. no Registrant."); 1635 } 1636 } 1637 1638 /** Notify all the registrants of the Slot loaded after carrier config loading is Completed */ notifyQnsConfigurationsChanged()1639 protected void notifyQnsConfigurationsChanged() { 1640 1641 if (mQnsCarrierConfigChangedRegistrants != null) { 1642 mQnsCarrierConfigChangedRegistrants.notifyRegistrants(); 1643 } else { 1644 Log.d(mLogTag, "notifyQnsConfigurationsChanged. no Registrant."); 1645 } 1646 } 1647 1648 /** 1649 * API exposed for other classes to register for notification with handlers on Carrier 1650 * Configuration Loaded 1651 * 1652 * @param h Handler to receive event 1653 * @param what Event on which to be handled 1654 */ registerForConfigurationLoaded(Handler h, int what)1655 void registerForConfigurationLoaded(Handler h, int what) { 1656 mQnsCarrierConfigLoadedRegistrants.addUnique(h, what, null); 1657 if (mIsConfigLoaded) { 1658 // notify the handler if config is already loaded. 1659 h.sendEmptyMessage(what); 1660 } 1661 } 1662 1663 /** 1664 * API exposed for other classes to register for notification with handlers on Carrier 1665 * Configuration changed 1666 * 1667 * @param h Handler to receive event 1668 * @param what Event on which to be handled 1669 */ registerForConfigurationChanged(Handler h, int what)1670 void registerForConfigurationChanged(Handler h, int what) { 1671 mQnsCarrierConfigChangedRegistrants.addUnique(h, what, null); 1672 } 1673 1674 /** 1675 * API exposed for other classes to unregister for notification of QNS Configuration loaded with 1676 * handlers 1677 * 1678 * @param h Handler to Unregister receiving event Output : Void 1679 */ unregisterForConfigurationLoaded(Handler h)1680 void unregisterForConfigurationLoaded(Handler h) { 1681 mQnsCarrierConfigLoadedRegistrants.remove(h); 1682 } 1683 1684 /** 1685 * API exposed for other classes to unregister for notification of QNS Configuration changed 1686 * with handlers 1687 * 1688 * @param h Handler to Unregister receiving event Output : Void 1689 */ unregisterForConfigurationChanged(Handler h)1690 void unregisterForConfigurationChanged(Handler h) { 1691 mQnsCarrierConfigChangedRegistrants.remove(h); 1692 } 1693 1694 /** 1695 * This method returns if WFC is supported in Airplane Mode On 1696 * 1697 * @return : boolean (True/False) 1698 */ allowWFCOnAirplaneModeOn()1699 boolean allowWFCOnAirplaneModeOn() { 1700 1701 return mIsWfcInAirplaneModeOnSupport; 1702 } 1703 1704 /** 1705 * This method returns if in-call handover decision from WLAN to WWAN should not consider VoPS 1706 * status. 1707 * 1708 * @return True if in-call handover decision from WLAN to WWAN should not consider VoPS status, 1709 * otherwise false. 1710 */ isInCallHoDecisionWlanToWwanWithoutVopsCondition()1711 boolean isInCallHoDecisionWlanToWwanWithoutVopsCondition() { 1712 return mIsInCallHoDecisionWlanToWwanWithoutVopsConditionSupported; 1713 } 1714 1715 /** 1716 * This method returns VOPS/VONR bit is required for WWAN availability. 1717 * 1718 * @return : boolean (True/False) 1719 */ isMmtelCapabilityRequired(int coverage)1720 boolean isMmtelCapabilityRequired(int coverage) { 1721 if (mIsMmtelCapabilityRequired == null || mIsMmtelCapabilityRequired.length == 0) { 1722 return true; 1723 } 1724 for (int i : mIsMmtelCapabilityRequired) { 1725 if ((i == CarrierConfigManager.Ims.NETWORK_TYPE_HOME 1726 && coverage == QnsConstants.COVERAGE_HOME) 1727 || (i == CarrierConfigManager.Ims.NETWORK_TYPE_ROAMING 1728 && coverage == QnsConstants.COVERAGE_ROAM)) { 1729 return false; 1730 } 1731 } 1732 return true; 1733 } 1734 1735 /** 1736 * This method returns if VoLTE roaming is supported by a carrier. 1737 * 1738 * @return True if VoLTE roaming is supported or UE is in home network, otherwise false. 1739 */ isVolteRoamingSupported(@nsConstants.CellularCoverage int coverage)1740 boolean isVolteRoamingSupported(@QnsConstants.CellularCoverage int coverage) { 1741 if (coverage == QnsConstants.COVERAGE_ROAM) { 1742 return mIsVolteRoamingSupported; 1743 } 1744 return true; 1745 } 1746 1747 /** 1748 * This method returns Video call over WFC with wfc off & LTE preconditions met 1749 * 1750 * @return : boolean (True/False) 1751 */ allowVideoOverIWLANWithCellularLimitedCase()1752 boolean allowVideoOverIWLANWithCellularLimitedCase() { 1753 return mIsVideoOverIWLANWithCellularCheckSupport; 1754 } 1755 1756 /** 1757 * This method returns if handover is allowed by policy 1758 * 1759 * @return True if handover is allowed by policy, otherwise false. 1760 */ isHandoverAllowedByPolicy( int netCapability, int srcAn, int destAn, @QnsConstants.CellularCoverage int coverage)1761 boolean isHandoverAllowedByPolicy( 1762 int netCapability, int srcAn, int destAn, @QnsConstants.CellularCoverage int coverage) { 1763 Log.d( 1764 mLogTag, 1765 "isHandoverAllowedByPolicy netCapability: " 1766 + QnsUtils.getNameOfNetCapability(netCapability) 1767 + " srcAccessNetwork:" 1768 + QnsConstants.accessNetworkTypeToString(srcAn) 1769 + " destAccessNetwork:" 1770 + QnsConstants.accessNetworkTypeToString(destAn) 1771 + " " 1772 + QnsConstants.coverageToString(coverage)); 1773 // check Telephony handover policy. 1774 // Matching the rules by the configured order. Bail out if find first matching rule. 1775 for (HandoverRule rule : mHandoverRuleList) { 1776 if (rule.mIsOnlyForRoaming && coverage != QnsConstants.COVERAGE_ROAM) continue; 1777 1778 if (rule.mSourceAccessNetworks.contains(srcAn) 1779 && rule.mTargetAccessNetworks.contains(destAn)) { 1780 // if no capability rule specified, data network capability is considered matched. 1781 // otherwise, any capabilities overlap is also considered matched. 1782 if (rule.mNetworkCapabilities.isEmpty() 1783 || rule.mNetworkCapabilities.contains(netCapability)) { 1784 if (rule.mHandoverRuleType == HandoverRule.RULE_TYPE_DISALLOWED) { 1785 Log.d(mLogTag, "isHandoverAllowedByPolicy:Not allowed by policy " + rule); 1786 return false; 1787 } else { 1788 Log.d(mLogTag, "isHandoverAllowedByPolicy: allowed by policy " + rule); 1789 return true; 1790 } 1791 } 1792 } 1793 } 1794 1795 Log.d(mLogTag, "isHandoverAllowedByPolicy: Did not find matching rule. "); 1796 // Disallow handover for non-IMS network capability anyway if no rule is found. 1797 if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) return false; 1798 1799 // Allow handover for IMS network capability anyway if no rule is found. 1800 return true; 1801 } 1802 1803 /** 1804 * This method returns if Service Barring Check for HO decision is Supported 1805 * 1806 * @return : boolean (True/False) 1807 */ isServiceBarringCheckSupported()1808 boolean isServiceBarringCheckSupported() { 1809 1810 return mIsServiceBarringCheckSupport; 1811 } 1812 1813 /** 1814 * This method returns if the Guard timer (Ping Pong) hysteresis is preference specific 1815 * 1816 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1817 * True / False 1818 */ isGuardTimerHysteresisOnPrefSupported()1819 boolean isGuardTimerHysteresisOnPrefSupported() { 1820 1821 return mIsHoGuardOnPreferenceSupport; 1822 } 1823 1824 /** 1825 * This method returns if the network(HOME or ROAM) requires handover guard timer. 1826 * 1827 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1828 * True / False 1829 */ isHysteresisTimerEnabled(int coverage)1830 boolean isHysteresisTimerEnabled(int coverage) { 1831 if (mNetworkEnableHysteresisTimer == QnsConstants.COVERAGE_BOTH 1832 || mNetworkEnableHysteresisTimer == coverage) { 1833 return true; 1834 } 1835 return false; 1836 } 1837 1838 /** 1839 * Get carrier config for the KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL if 1840 * true, It ignores all thresholds needed to only refer to availability. 1841 * 1842 * @return true for key value is true. False for otherwise. 1843 */ isTransportTypeSelWithoutSSInRoamSupported()1844 boolean isTransportTypeSelWithoutSSInRoamSupported() { 1845 1846 return mAnspSupportConfigArray[0]; 1847 } 1848 1849 /* 1850 * get carrierconfig for KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL 1851 * true: Prefer current transport type during voice call. 1852 * 1853 * @return true for key value is true. False for otherwise. 1854 */ isCurrentTransportTypeInVoiceCallSupported()1855 boolean isCurrentTransportTypeInVoiceCallSupported() { 1856 1857 return mAnspSupportConfigArray[1]; 1858 } 1859 1860 /** 1861 * Get carrierconfig for KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL 1862 * true: Use IMS Preferred when WFC Mode is Cellular Preferred at Home Network. 1863 * 1864 * @return true for key value is true. False for otherwise. 1865 */ isOverrideImsPreferenceSupported()1866 boolean isOverrideImsPreferenceSupported() { 1867 return mAnspSupportConfigArray[2]; 1868 } 1869 1870 /** 1871 * The method is to return if choose WFC prferred transport in both WWAN and WLAN are bad 1872 * conditions. It is controlled by 1873 * KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY. 1874 * 1875 * @return : boolean (True/False) 1876 */ isChooseWfcPreferredTransportInBothBadCondition(int wfcMode)1877 boolean isChooseWfcPreferredTransportInBothBadCondition(int wfcMode) { 1878 if (mIsWfcPreferredTransportRequired == null 1879 || mIsWfcPreferredTransportRequired.length == 0) { 1880 return false; 1881 } 1882 for (int i : mIsWfcPreferredTransportRequired) { 1883 if (wfcMode == i) { 1884 return true; 1885 } 1886 } 1887 return false; 1888 } 1889 1890 /** 1891 * This method returns whether the rove out(to Cellular) policy includes a Wi-Fi bad condition 1892 * at handover guarding time. 1893 * 1894 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1895 * True / False 1896 */ isRoveOutWithWiFiLowQualityAtGuardingTime()1897 boolean isRoveOutWithWiFiLowQualityAtGuardingTime() { 1898 1899 return mIsRoveOutWifiBadGuardTimerConditionsSupported; 1900 } 1901 1902 /** 1903 * This method returns the waiting time for the preferred transport type at power up. 1904 * 1905 * @return : A timer in millisecond 1906 */ getWaitingTimerForPreferredTransportOnPowerOn(int transportType)1907 int getWaitingTimerForPreferredTransportOnPowerOn(int transportType) { 1908 switch (transportType) { 1909 case TRANSPORT_TYPE_WWAN: 1910 return mWaitingTimerForPreferredTransport[0]; 1911 case TRANSPORT_TYPE_WLAN: 1912 return mWaitingTimerForPreferredTransport[1]; 1913 default: 1914 Log.d(mLogTag, "Invalid transport type, return the default timer."); 1915 return QnsConstants.KEY_DEFAULT_VALUE; 1916 } 1917 } 1918 1919 /** 1920 * This method returns the Transport type Preference on Power On. 1921 * 1922 * @return : Based on Carrier Config Settings Possible values (3000msec:Default or operator 1923 * customisation. 1924 */ getWIFIRssiBackHaulTimer()1925 int getWIFIRssiBackHaulTimer() { 1926 return mWifiThresBackHaulTimer; 1927 } 1928 1929 /** 1930 * This method returns Cellular SS Backhaul Timer. 1931 * 1932 * @return : Based on Carrier Config Settings based on operator requirement possible values ( 0 1933 * : Invalid or 320ms) 1934 */ getCellularSSBackHaulTimer()1935 int getCellularSSBackHaulTimer() { 1936 1937 return mCellularThresBackHaulTimer; 1938 } 1939 1940 /** 1941 * This method returns IWLAN HO Avoid time due to Low RTP Quality Backhaul Timer. 1942 * 1943 * @return : Based on Carrier Config Settings based on operator requirement possible values ( 0 1944 * : or operator requirement) 1945 */ getHoRestrictedTimeOnLowRTPQuality( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork)1946 int getHoRestrictedTimeOnLowRTPQuality( 1947 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork) { 1948 1949 if (accessNetwork == TRANSPORT_TYPE_WLAN) { 1950 return mHoRestrictTimeOnRtpQuality[0]; 1951 } else if (accessNetwork == TRANSPORT_TYPE_WWAN) { 1952 return mHoRestrictTimeOnRtpQuality[1]; 1953 } else { 1954 return QnsConstants.KEY_DEFAULT_VALUE; 1955 } 1956 } 1957 1958 /** 1959 * This method returns QNS preferred transport type for network capabilities / Services 1960 * 1961 * @return : Based on Carrier Config Settings based on operator requirement possible values: 1962 * TRANSPORT_TYPE_ALLOWED_WWAN = 0 TRANSPORT_TYPE_ALLOWED_IWLAN = 1 1963 * TRANSPORT_TYPE_ALLOWED_BOTH = 2 1964 */ getQnsSupportedTransportType(int netCapability)1965 int getQnsSupportedTransportType(int netCapability) { 1966 if (netCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { 1967 return mQnsImsTransportType; 1968 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) { 1969 return mQnsSosTransportType; 1970 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_MMS) { 1971 return mQnsMmsTransportType; 1972 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_XCAP) { 1973 HashSet<Integer> supportedTransportType = new HashSet<>(); 1974 if (mQnsXcapSupportedAccessNetworkTypes != null) { 1975 Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 1976 .forEach(accessNetwork -> supportedTransportType.add( 1977 QnsUtils.getTransportTypeFromAccessNetwork(accessNetwork))); 1978 } 1979 if (supportedTransportType.contains(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)) { 1980 if (supportedTransportType.contains(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) { 1981 return QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH; 1982 } 1983 return QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN; 1984 } 1985 return QnsConstants.TRANSPORT_TYPE_ALLOWED_WWAN; 1986 } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_CBS) { 1987 return mQnsCbsTransportType; 1988 } 1989 return QnsConstants.INVALID_ID; 1990 } 1991 1992 /** 1993 * This method returns the hysteresis timer when handover from WLAN to WWAN. 1994 * 1995 * @return : the hysteresis timer 1996 */ getWwanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType)1997 int getWwanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType) { 1998 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC)) { 1999 return mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC); 2000 } 2001 switch (netCapability) { 2002 case NetworkCapabilities.NET_CAPABILITY_IMS: 2003 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2004 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2005 return mWwanHysteresisTimer[0]; 2006 } else if (callType == QnsConstants.CALL_TYPE_VOICE) { 2007 return mWwanHysteresisTimer[1]; 2008 } else if (callType == QnsConstants.CALL_TYPE_VIDEO) { 2009 return mWwanHysteresisTimer[2]; 2010 } else { 2011 return QnsConstants.KEY_DEFAULT_VALUE; 2012 } 2013 case NetworkCapabilities.NET_CAPABILITY_MMS: 2014 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2015 case NetworkCapabilities.NET_CAPABILITY_CBS: 2016 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2017 return mNonImsWwanHysteresisTimer[0]; 2018 } else { 2019 return mNonImsWwanHysteresisTimer[1]; 2020 } 2021 default: 2022 return QnsConstants.KEY_DEFAULT_VALUE; 2023 } 2024 } 2025 2026 /** 2027 * This method returns the hysteresis timer when handover from WWAN to WLAN. 2028 * 2029 * @return : the hysteresis timer 2030 */ getWlanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType)2031 int getWlanHysteresisTimer(int netCapability, @QnsConstants.QnsCallType int callType) { 2032 if (mQnsProvisioningInfo.hasItem(ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC)) { 2033 return mQnsProvisioningInfo.getIntegerItem(ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC); 2034 } 2035 switch (netCapability) { 2036 case NetworkCapabilities.NET_CAPABILITY_IMS: 2037 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2038 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2039 return mWlanHysteresisTimer[0]; 2040 } else if (callType == QnsConstants.CALL_TYPE_VOICE) { 2041 return mWlanHysteresisTimer[1]; 2042 } else if (callType == QnsConstants.CALL_TYPE_VIDEO) { 2043 return mWlanHysteresisTimer[2]; 2044 } else { 2045 return QnsConstants.KEY_DEFAULT_VALUE; 2046 } 2047 case NetworkCapabilities.NET_CAPABILITY_MMS: 2048 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2049 case NetworkCapabilities.NET_CAPABILITY_CBS: 2050 if (callType == QnsConstants.CALL_TYPE_IDLE) { 2051 return mNonImsWlanHysteresisTimer[0]; 2052 } else { 2053 return mNonImsWlanHysteresisTimer[1]; 2054 } 2055 default: 2056 return QnsConstants.KEY_DEFAULT_VALUE; 2057 } 2058 } 2059 2060 /** 2061 * This method returns the timer millis for the minimum guarding timer. 2062 * 2063 * @return the minimum guarding timer in millis. applies when handover guarding is disabled or 2064 * there is no guarding time. 2065 */ getMinimumHandoverGuardingTimer()2066 int getMinimumHandoverGuardingTimer() { 2067 int timer = mMinimumHandoverGuardingTimer; 2068 if (timer <= 0) { 2069 return 0; 2070 } 2071 if (timer >= QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT) { 2072 timer = QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT; 2073 } 2074 return timer; 2075 } 2076 2077 /** 2078 * This method returns the Threshold gap offset based on which threshold to be registered during 2079 * Guard timer Running / Expired conditions from Evaluator 2080 * 2081 * @return : Based on Carrier Config Settings & operator requirement Default Value : 0 gap 2082 * offset (Means different threshold for Guard timer conditions not enabled) 2083 */ getThresholdGapWithGuardTimer( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType)2084 int getThresholdGapWithGuardTimer( 2085 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType) { 2086 2087 return getValueForMeasurementType( 2088 accessNetwork, measType, mRoveInGuardTimerConditionThresholdGaps); 2089 2090 } 2091 2092 /** 2093 * This method returns hysteresis Dbm level for ran and measurement type configured. 2094 * 2095 * @return : Based on Carrier Config Settings & operator requirement Default Value. 2096 * Note: If configured value set is less than zero or not set, 2097 * {@link QnsConstants#KEY_DEFAULT_VALUE} 2098 */ getWwanHysteresisDbLevel( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType)2099 public int getWwanHysteresisDbLevel( 2100 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType) { 2101 2102 int hysteresisDb = getValueForMeasurementType( 2103 accessNetwork, measType, mAccessNetworkMeasurementHysteresisDb); 2104 return hysteresisDb >= 0 ? hysteresisDb : QnsConstants.KEY_DEFAULT_VALUE; 2105 } 2106 getValueForMeasurementType( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType, String [] measurementValues)2107 private int getValueForMeasurementType( 2108 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int measType, 2109 String [] measurementValues) { 2110 2111 if (measurementValues == null) { 2112 return QnsConstants.KEY_DEFAULT_VALUE; 2113 } 2114 2115 for (String check_offset : measurementValues) { 2116 if (check_offset == null || check_offset.isEmpty()) continue; 2117 String[] value = check_offset.split(":"); 2118 String access_network = sAccessNetworkMap.get(accessNetwork); 2119 String measurement_Type = sMeasTypeMap.get(measType); 2120 try { 2121 if (value.length == 3 && value[0].equalsIgnoreCase(access_network) 2122 && value[1].equalsIgnoreCase(measurement_Type)) { 2123 return Integer.parseInt(value[2]); 2124 } 2125 } catch (Exception e) { 2126 e.printStackTrace(); 2127 } 2128 } 2129 return QnsConstants.KEY_DEFAULT_VALUE; 2130 } 2131 hasThresholdGapWithGuardTimer()2132 boolean hasThresholdGapWithGuardTimer() { 2133 if (mRoveInGuardTimerConditionThresholdGaps == null) { 2134 return false; 2135 } 2136 return true; 2137 } 2138 2139 /** 2140 * This method returns Access Network Selection Policy based on network capability 2141 * 2142 * @param targetTransportType : WWAN/WLAN 2143 * @return : Target transport mapped to string 2144 */ transportNetworkToString(int targetTransportType)2145 static String transportNetworkToString(int targetTransportType) { 2146 switch (targetTransportType) { 2147 case TRANSPORT_TYPE_WWAN: 2148 return "CELLULAR"; 2149 case TRANSPORT_TYPE_WLAN: 2150 return "WIFI"; 2151 } 2152 return ""; 2153 } 2154 2155 /** 2156 * Finds and returns a threshold config that meets the given parameter condition. 2157 * 2158 * @param accessNetwork (EUTRAN/UTRAN/NGRAN/GERAN/IWLAN) 2159 * @param callType (IDLE/VOICE/VIDEO) 2160 * @param measurementType (RSRP/RSRQ/RSSNR/SSRSP/SSRSQ/RSCP/RSSI) 2161 * @return QnsConfigArray for good, bad and worst thresholds. If the value does not exist or is 2162 * not supported, it is filled with invalid (0x0000FFFF). Note, for the wifi case, the worst 2163 * in thresholds will be invalid. INVALID VALUE, if not found item or exceptions. 2164 */ getThreshold( @ccessNetworkConstants.RadioAccessNetworkType int accessNetwork, int callType, int measurementType)2165 QnsConfigArray getThreshold( 2166 @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork, 2167 int callType, 2168 int measurementType) { 2169 int[] thresholdList = new int[] {0x0000FFFF, 0x0000FFFF, 0x0000FFFF}; 2170 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.UNKNOWN 2171 || measurementType == SIGNAL_MEASUREMENT_TYPE_UNKNOWN) { 2172 return null; 2173 } 2174 2175 String access_network = sAccessNetworkMap.get(accessNetwork); 2176 String measurement_Type = sMeasTypeMap.get(measurementType); 2177 String call_Type = sCallTypeMap.get(callType); 2178 2179 if (access_network != null && measurement_Type != null && call_Type != null) { 2180 String key = 2181 "qns." 2182 + call_Type 2183 + "_" 2184 + access_network 2185 + "_" 2186 + measurement_Type 2187 + "_" 2188 + "int_array"; 2189 2190 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2191 2192 if (thresholdList != null && thresholdList.length > 1) { 2193 if (AccessNetworkConstants.AccessNetworkType.IWLAN == accessNetwork 2194 || thresholdList.length == 2) { 2195 return new QnsConfigArray(thresholdList[0], thresholdList[1]); 2196 } else { 2197 return new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2198 } 2199 } else { 2200 thresholdList = new int[] {0x0000FFFF, 0x0000FFFF, 0x0000FFFF}; 2201 } 2202 } 2203 return new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2204 } 2205 getThresholdByPref( int accessNetwork, int callType, int measurementType, int preference)2206 QnsConfigArray getThresholdByPref( 2207 int accessNetwork, int callType, int measurementType, int preference) { 2208 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.UNKNOWN 2209 || measurementType == SIGNAL_MEASUREMENT_TYPE_UNKNOWN) { 2210 return null; 2211 } 2212 2213 int[] thresholdList = null; 2214 String access_network = sAccessNetworkMap.get(accessNetwork); 2215 String measurement_Type = sMeasTypeMap.get(measurementType); 2216 String call_Type = sCallTypeMap.get(callType); 2217 2218 if (access_network == null || measurement_Type == null || call_Type == null) { 2219 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2220 } 2221 2222 if (accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN 2223 && preference == QnsConstants.WIFI_PREF) { 2224 String overrideKey = 2225 "qns.override_wifi_pref_" 2226 + call_Type 2227 + "_" 2228 + access_network 2229 + "_" 2230 + measurement_Type 2231 + "_int_array"; 2232 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(overrideKey); 2233 } 2234 2235 if (thresholdList == null || thresholdList.length < 2) { 2236 String key = 2237 "qns." 2238 + call_Type 2239 + "_" 2240 + access_network 2241 + "_" 2242 + measurement_Type 2243 + "_int_array"; 2244 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2245 } 2246 if (thresholdList == null || thresholdList.length < 2) { 2247 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2248 } 2249 2250 if (AccessNetworkConstants.AccessNetworkType.IWLAN == accessNetwork 2251 || thresholdList.length == 2) { 2252 QnsConfigArray qnsConfigArray = new QnsConfigArray(thresholdList[0], thresholdList[1]); 2253 return applyProvisioningInfo(qnsConfigArray, accessNetwork, measurementType, callType); 2254 } 2255 2256 QnsConfigArray qnsConfigArray = 2257 new QnsConfigArray(thresholdList[0], thresholdList[1], thresholdList[2]); 2258 return applyProvisioningInfo(qnsConfigArray, accessNetwork, measurementType, callType); 2259 } 2260 getWifiRssiThresholdWithoutCellular(int callType)2261 QnsConfigArray getWifiRssiThresholdWithoutCellular(int callType) { 2262 int[] thresholdList; 2263 String call_Type = sCallTypeMap.get(callType); 2264 2265 if (call_Type == null) { 2266 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2267 } 2268 2269 String key = "qns." + call_Type + "_wifi_rssi_without_cellular_int_array"; 2270 thresholdList = mAnspConfigMgr.getAnspCarrierThreshold(key); 2271 2272 if (thresholdList == null || thresholdList.length < 2) { 2273 return new QnsConfigArray(0x0000FFFF, 0x0000FFFF, 0x0000FFFF); 2274 } 2275 2276 return new QnsConfigArray(thresholdList[0], thresholdList[1]); 2277 } 2278 2279 /** 2280 * Finds and returns a policy config that meets the given parameter condition. 2281 * 2282 * @param direction (ROVE_IN / ROVE_OUT) 2283 * @param preCondition (Types of CALL, PREFERENCE, COVERAGE and so on) 2284 * @return QnsConfigArray for good, bad and worst policy. If the value does not exist or is not 2285 * supported, it is filled with invalid. (0x0000FFFF). Note, for the wifi case, the worst in 2286 * thresholds will be invalid. null, if not found item or exceptions. 2287 */ getPolicy( @nsConstants.RoveDirection int direction, AccessNetworkSelectionPolicy.PreCondition preCondition)2288 String[] getPolicy( 2289 @QnsConstants.RoveDirection int direction, 2290 AccessNetworkSelectionPolicy.PreCondition preCondition) { 2291 2292 String key = 2293 "qns.condition_" 2294 + QnsConstants.directionToString(direction).toLowerCase() 2295 + "_" 2296 + QnsConstants.callTypeToString(preCondition.getCallType()).toLowerCase() 2297 + "_" 2298 + QnsConstants.preferenceToString(preCondition.getPreference()) 2299 .toLowerCase() 2300 + "_" 2301 + QnsConstants.coverageToString(preCondition.getCoverage()).toLowerCase() 2302 + "_"; 2303 2304 if (preCondition instanceof AccessNetworkSelectionPolicy.GuardingPreCondition) { 2305 AccessNetworkSelectionPolicy.GuardingPreCondition guardingCondition = 2306 (AccessNetworkSelectionPolicy.GuardingPreCondition) preCondition; 2307 String guardingKey = 2308 key 2309 + QnsConstants.guardingToString(guardingCondition.getGuarding()) 2310 .toLowerCase() 2311 + "_string_array"; 2312 String[] guardingPolicy = mAnspConfigMgr.getAnspCarrierPolicy(guardingKey); 2313 if (guardingPolicy != null) { 2314 return guardingPolicy; 2315 } 2316 } 2317 key = key + "string_array"; 2318 return mAnspConfigMgr.getAnspCarrierPolicy(key); 2319 } 2320 2321 /** 2322 * This method returns RTP Metrics data of Carrier for HO decision making 2323 * 2324 * @return config of RTP metrics. refer {@link RtpMetricsConfig} 2325 */ 2326 @VisibleForTesting getRTPMetricsData()2327 RtpMetricsConfig getRTPMetricsData() { 2328 2329 return new RtpMetricsConfig( 2330 mRTPMetricsData[0], mRTPMetricsData[1], mRTPMetricsData[2], mRTPMetricsData[3]); 2331 } 2332 2333 /** 2334 * This retrieves fallback timer to WWAN with the reason of IMS unregistered. 2335 * 2336 * @return fallback time in millis. 2337 */ 2338 @VisibleForTesting getFallbackTimeImsUnregistered(int reason, int preferMode)2339 int getFallbackTimeImsUnregistered(int reason, int preferMode) { 2340 Log.d( 2341 mLogTag, 2342 "getFallbackTimeImsUnregistered reason:" + reason + " prefMode:" + preferMode); 2343 for (FallbackRule rule : mFallbackWwanRuleWithImsUnregistered) { 2344 Log.d(mLogTag, rule.toString()); 2345 if (preferMode != QnsConstants.WIFI_ONLY 2346 && (rule.mPreferenceMode == -1 || rule.mPreferenceMode == preferMode)) { 2347 int time = rule.getFallBackTime(reason); 2348 if (time > 0) { 2349 Log.d(mLogTag, "getFallbackTimeImsUnregistered fallbackTime:" + time); 2350 return time; 2351 } 2352 } 2353 } 2354 Log.d(mLogTag, "getFallbackTimeImsUnregistered fallbackTime:" + 0); 2355 return 0; 2356 } 2357 2358 /** 2359 * This retrieves fallback timer to WWAN with the reason of IMS HO register fail. 2360 * 2361 * @return fallback time in millis. 2362 */ 2363 @VisibleForTesting getFallbackTimeImsHoRegisterFailed(int reason, int preferMode)2364 int getFallbackTimeImsHoRegisterFailed(int reason, int preferMode) { 2365 Log.d( 2366 mLogTag, 2367 "getFallbackTimeImsHoRegisterFailed reason:" + reason + " prefMode:" + preferMode); 2368 for (FallbackRule rule : mFallbackWwanRuleWithImsHoRegisterFail) { 2369 if (preferMode != QnsConstants.WIFI_ONLY 2370 && (rule.mPreferenceMode == -1 || rule.mPreferenceMode == preferMode)) { 2371 Log.d(mLogTag, rule.toString()); 2372 int time = rule.getFallBackTime(reason); 2373 Log.d(mLogTag, "getFallbackTimeImsHoRegisterFailed fallback time: " + time); 2374 if (time > 0) return time; 2375 } 2376 } 2377 Log.d(mLogTag, "getFallbackTimeImsHoRegisterFailed fallback time: " + 0); 2378 return 0; 2379 } 2380 2381 /** 2382 * This method returns Access Network Selection Policy Support configurations with boolean array 2383 * list type 2384 * 2385 */ loadAnspCarrierSupportConfigs( PersistableBundle bundleCarrier, PersistableBundle bundleAsset)2386 void loadAnspCarrierSupportConfigs( 2387 PersistableBundle bundleCarrier, PersistableBundle bundleAsset) { 2388 int i = 0; 2389 String[] anspConfigs = { 2390 KEY_ROAM_TRANSPORT_TYPE_SELECTION_WITHOUT_SIGNAL_STRENGTH_BOOL, 2391 KEY_PREFER_CURRENT_TRANSPORT_TYPE_IN_VOICE_CALL_BOOL, 2392 KEY_POLICY_OVERRIDE_CELL_PREF_TO_IMS_PREF_HOME_BOOL 2393 }; 2394 2395 for (String key : anspConfigs) { 2396 mAnspSupportConfigArray[i] = getConfig(bundleCarrier, bundleAsset, key); 2397 i += 1; 2398 } 2399 2400 mIsWfcPreferredTransportRequired = 2401 getConfig( 2402 bundleCarrier, 2403 bundleAsset, 2404 KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY); 2405 } 2406 2407 /** 2408 * This method gives the network capabilities supported based on 2409 * KEY_QNS_<NetworkCapability></NetworkCapability>_TRANSPORT_TYPE_INT 2410 * 2411 * @return : Supported network capabilities 2412 */ getQnsSupportedNetCapabilities()2413 List<Integer> getQnsSupportedNetCapabilities() { 2414 List<Integer> netCapabilities = new ArrayList<>(); 2415 if (mQnsImsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2416 || mQnsImsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2417 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_IMS); 2418 } 2419 if (mQnsSosTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2420 || mQnsSosTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2421 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_EIMS); 2422 } 2423 if (mQnsMmsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2424 || mQnsMmsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2425 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_MMS); 2426 } 2427 if (mQnsXcapSupportedAccessNetworkTypes != null 2428 && Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 2429 .anyMatch(accessNetwork -> QnsUtils.getTransportTypeFromAccessNetwork( 2430 accessNetwork) == AccessNetworkConstants.TRANSPORT_TYPE_WLAN)) { 2431 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_XCAP); 2432 } 2433 if (mQnsCbsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_IWLAN 2434 || mQnsCbsTransportType == QnsConstants.TRANSPORT_TYPE_ALLOWED_BOTH) { 2435 netCapabilities.add(NetworkCapabilities.NET_CAPABILITY_CBS); 2436 } 2437 return netCapabilities; 2438 } 2439 2440 private static HashMap<Integer, String> sRatStringMatcher; 2441 static { 2442 sRatStringMatcher = new HashMap<>(); sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.EUTRAN, "LTE")2443 sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.EUTRAN, "LTE"); sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.NGRAN, "NR")2444 sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.NGRAN, "NR"); sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.UTRAN, "3G")2445 sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.UTRAN, "3G"); sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.GERAN, "2G")2446 sRatStringMatcher.put(AccessNetworkConstants.AccessNetworkType.GERAN, "2G"); 2447 } 2448 2449 /** 2450 * This method returns Allowed cellular RAT for IMS 2451 * 2452 * @param accessNetwork : (EUTRAN, NGRAN, UTRAN, GERAN) 2453 * @param netCapability : (ims, sos, mms, xcap, cbs) 2454 * @return : True or False based on configuration 2455 */ isAccessNetworkAllowed(int accessNetwork, int netCapability)2456 boolean isAccessNetworkAllowed(int accessNetwork, int netCapability) { 2457 2458 switch (netCapability) { 2459 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2460 case NetworkCapabilities.NET_CAPABILITY_IMS: 2461 // cases to be enhanced for different key items when added 2462 String ratName = sRatStringMatcher.get(accessNetwork); 2463 if (mImsAllowedRats != null 2464 && ratName != null 2465 && Arrays.stream(mImsAllowedRats) 2466 .anyMatch(ratType -> TextUtils.equals(ratType, ratName))) { 2467 return true; 2468 } 2469 break; 2470 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2471 return mQnsXcapSupportedAccessNetworkTypes != null 2472 && Arrays.stream(mQnsXcapSupportedAccessNetworkTypes) 2473 .anyMatch(xcapAccessNetwork -> accessNetwork == xcapAccessNetwork); 2474 default: 2475 return false; 2476 } 2477 return false; 2478 } 2479 2480 /** 2481 * This method returns max HO Back to IWLAN count value with Fallback reason to Rove Out 2482 * 2483 * @return : int array (Ex: -1,-1 or 1,2 or 3,1 etc... ) 2484 */ getQnsMaxIwlanHoCountDuringCall()2485 int getQnsMaxIwlanHoCountDuringCall() { 2486 2487 if (mAllowMaxIwlanHoCountOnReason[0] <= 0) { 2488 mAllowMaxIwlanHoCountOnReason[0] = MAX_COUNT_INVALID; 2489 } 2490 2491 return mAllowMaxIwlanHoCountOnReason[0]; 2492 } 2493 2494 /** 2495 * This method returns Supported Fallback reason to Rove Out from IWLAN 2496 * 2497 * @return : int array (Ex: -1,-1 or 1,2 or 3,1 etc... ) 2498 */ getQnsIwlanHoRestrictReason()2499 int getQnsIwlanHoRestrictReason() { 2500 if (mAllowMaxIwlanHoCountOnReason[1] <= 0) { 2501 mAllowMaxIwlanHoCountOnReason[1] = FALLBACK_REASON_INVALID; 2502 } 2503 return mAllowMaxIwlanHoCountOnReason[1]; 2504 } 2505 2506 /** 2507 * This method returns to allow enabled Wi-Fi calling based on exceptional cellular state, even 2508 * when Wi-Fi calling is disabled. 2509 * 2510 * <p>Enable Wi-Fi calling If the call state is idle and the cellular network the UE is staying 2511 * on does not allow ims pdn. 2512 * 2513 * @return : Based on Carrier Config Settings based on operator requirement possible values: 2514 * True / False 2515 */ allowImsOverIwlanCellularLimitedCase()2516 boolean allowImsOverIwlanCellularLimitedCase() { 2517 return mIsAllowImsOverIwlanCellularLimitedCase; 2518 } 2519 2520 /** 2521 * This method returns if Iwlan is not allowed when UE is in no WWAN coverage and the last 2522 * stored country code is outside the home country. 2523 * 2524 * @return True if need to block Iwlan, otherwise false. 2525 */ blockIwlanInInternationalRoamWithoutWwan()2526 boolean blockIwlanInInternationalRoamWithoutWwan() { 2527 return mIsBlockIwlanInInternationalRoamWithoutWwan; 2528 } 2529 2530 /** 2531 * This method returns if IPv6 only WiFi is allowed 2532 * 2533 * @return True if need to block IPv6 only WiFi, otherwise false. 2534 */ blockIpv6OnlyWifi()2535 boolean blockIpv6OnlyWifi() { 2536 return mIsBlockIpv6OnlyWifi; 2537 } 2538 2539 /** 2540 * This method returns the wait timer in milliseconds that VoWiFi registration in VoWiFi 2541 * activation process 2542 */ getVowifiRegistrationTimerForVowifiActivation()2543 int getVowifiRegistrationTimerForVowifiActivation() { 2544 return mVowifiRegistrationTimerForVowifiActivation; 2545 } 2546 2547 /** 2548 * This method returns whether the IMS Registration state option is added when reporting a 2549 * qualified Wi-Fi network for network capabilities other than ims. 2550 * 2551 * @return : Based on Carrier Config Settings based on operator requirement possible values: 2552 * True / False 2553 */ getRatPreference(int netCapability)2554 int getRatPreference(int netCapability) { 2555 switch (netCapability) { 2556 case NetworkCapabilities.NET_CAPABILITY_XCAP: 2557 return mXcapRatPreference; 2558 case NetworkCapabilities.NET_CAPABILITY_EIMS: 2559 return mSosRatPreference; 2560 case NetworkCapabilities.NET_CAPABILITY_MMS: 2561 return mMmsRatPreference; 2562 case NetworkCapabilities.NET_CAPABILITY_CBS: 2563 return mCbsRatPreference; 2564 } 2565 return QnsConstants.RAT_PREFERENCE_DEFAULT; 2566 } 2567 2568 /** 2569 * This method returns the rtt check server address config as per operator requirement 2570 * 2571 * @return Based on carrier config settings of operator. By default, to be made empty to 2572 * disable the feature. 2573 */ getWlanRttServerAddressConfig()2574 String getWlanRttServerAddressConfig() { 2575 String[] ping_address = getWlanRttPingConfigs(); 2576 2577 if (ping_address != null && ping_address[0] != null && !ping_address[0].isEmpty()) { 2578 return ping_address[0]; 2579 } else { 2580 return null; 2581 } 2582 } 2583 2584 /** 2585 * This method returns No of Pings, Intra Ping Interval, Size of the packet, RTT criteria RTT 2586 * retry timer 2587 * 2588 * @return : Based on carrier config settings as per operator requirement 2589 */ getWlanRttOtherConfigs()2590 int[] getWlanRttOtherConfigs() { 2591 int[] pingConfigs = new int[5]; 2592 String[] rtt_ping_config = getWlanRttPingConfigs(); 2593 2594 if (rtt_ping_config != null && !rtt_ping_config[0].isEmpty()) { 2595 for (int i = 1; i < 6; i++) { 2596 if (rtt_ping_config[i] != null) { 2597 pingConfigs[i - 1] = Integer.parseInt(rtt_ping_config[i]); 2598 } 2599 } 2600 } 2601 return pingConfigs; 2602 } 2603 2604 /** 2605 * This method returns fallback Hysteresis timer on RTT Failure. 2606 * 2607 * @return : Based on carrier config settings as per operator requirement 2608 */ getWlanRttFallbackHystTimer()2609 int getWlanRttFallbackHystTimer() { 2610 String[] rtt_hyst_fallback_timer = getWlanRttPingConfigs(); 2611 2612 if (rtt_hyst_fallback_timer != null 2613 && !rtt_hyst_fallback_timer[0].isEmpty() 2614 && rtt_hyst_fallback_timer[6] != null) { 2615 return Integer.parseInt(rtt_hyst_fallback_timer[6]); 2616 } else { 2617 return 0; 2618 } 2619 } 2620 getWlanRttPingConfigs()2621 private String[] getWlanRttPingConfigs() { 2622 if (mWlanRttBackhaulCheckConfigsOnPing == null) return null; 2623 2624 return mWlanRttBackhaulCheckConfigsOnPing.split(","); 2625 } 2626 2627 /** 2628 * If fallback for Initial connection failure for the network capability is met is supported , 2629 * this method provides information about the failure retry count or retry timer or both if 2630 * supported until fallback to other transport. 2631 * 2632 * @param netCapability : (ims,sos,mms,xcap,cbs) 2633 * @return : 2634 * <NetworkCapability_SupportForFallback>:<retry_count>:<retry_timer>:<max_fallback_count> 2635 */ getInitialDataConnectionFallbackConfig(int netCapability)2636 int[] getInitialDataConnectionFallbackConfig(int netCapability) { 2637 2638 int[] fallbackConfigOnDataFail = new int[4]; 2639 String[] fallback_config = getFallbackConfigForNetCapability(netCapability); 2640 2641 if (fallback_config != null 2642 && fallback_config[0] != null 2643 && fallback_config[0].length() > 0) { 2644 // netCapability Availability Status 2645 fallbackConfigOnDataFail[0] = 1; 2646 2647 // Retry Count : && fallback_config[1].length() > 0 2648 if (fallback_config.length > 1 2649 && fallback_config[1] != null 2650 && !fallback_config[1].isEmpty()) { 2651 fallbackConfigOnDataFail[1] = Integer.parseInt(fallback_config[1]); 2652 } 2653 2654 // Retry timer 2655 if (fallback_config.length > 2 2656 && fallback_config[2] != null 2657 && !fallback_config[2].isEmpty()) { 2658 fallbackConfigOnDataFail[2] = Integer.parseInt(fallback_config[2]); 2659 } 2660 2661 // Max fallback count 2662 if (fallback_config.length > 4 2663 && fallback_config[4] != null 2664 && !fallback_config[4].isEmpty()) { 2665 fallbackConfigOnDataFail[3] = Integer.parseInt(fallback_config[4]); 2666 } 2667 } 2668 return fallbackConfigOnDataFail; 2669 } 2670 2671 /** 2672 * This method returns the fall back timer to be starting the restriction , for no. of retries 2673 * when met with the pdn fail fallback causes 2674 * 2675 * @param netCapability : (ims,sos,mms,xcap,cbs) 2676 * @return : Fallback Guard timer to be set on starting the fallback restrict @ RestrictManager 2677 */ getFallbackGuardTimerOnInitialConnectionFail(int netCapability)2678 int getFallbackGuardTimerOnInitialConnectionFail(int netCapability) { 2679 String[] fallback_guard_timer = getFallbackConfigForNetCapability(netCapability); 2680 2681 if (fallback_guard_timer != null 2682 && fallback_guard_timer[0] != null 2683 && fallback_guard_timer[0].length() > 0 2684 && ((fallback_guard_timer.length > 1 2685 && fallback_guard_timer[1] != null 2686 && !fallback_guard_timer[1].isEmpty()) 2687 || (fallback_guard_timer.length > 2 2688 && fallback_guard_timer[2] != null 2689 && !fallback_guard_timer[2].isEmpty())) 2690 && (fallback_guard_timer.length > 3 2691 && fallback_guard_timer[3] != null 2692 && !fallback_guard_timer[3].isEmpty())) { 2693 return Integer.parseInt(fallback_guard_timer[3]); 2694 } else { 2695 return 0; 2696 } 2697 } 2698 2699 /** 2700 * To support find the right Initial Pdn connection failure fallback config based on network 2701 * capability 2702 */ getFallbackConfigForNetCapability(int netCapability)2703 private String[] getFallbackConfigForNetCapability(int netCapability) { 2704 if (mFallbackOnInitialConnectionFailure != null 2705 && mFallbackOnInitialConnectionFailure.length > 0) { 2706 String netCapabilityName = QnsUtils.getNameOfNetCapability(netCapability); 2707 for (String config : mFallbackOnInitialConnectionFailure) { 2708 Log.d(mLogTag, "Fallback On Initial Failure enabled for " + config); 2709 if (config.contains(netCapabilityName)) { 2710 return config.split(":"); 2711 } 2712 } 2713 } 2714 return null; 2715 } 2716 2717 /** 2718 * Get the Sip Dialog Session policy when the Sip Dialog State is active. This Sip Dialog 2719 * Session policy is applied when there is no calling in the subscription, and when the device 2720 * is in a calling state, the calling policy is used first. 2721 * 2722 * @return 0: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_NONE} not Applied. The default value 2723 * for this key. 1: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VOICE_CALL} apply voice 2724 * call policy. 2: {@code QnsConstants#SIP_DIALOG_SESSION_POLICY_FOLLOW_VIDEO_CALL} apply video 2725 * call policy. 2726 */ getSipDialogSessionPolicy()2727 @QnsConstants.QnsSipDialogSessionPolicy int getSipDialogSessionPolicy() { 2728 return mSipDialogSessionPolicy; 2729 } 2730 2731 static class QnsConfigArray { 2732 2733 /* 2734 * static invalid 2735 */ 2736 static final int INVALID = 0x0000FFFF; 2737 /* 2738 * Thresholds, A signal value of good strength to enter. 2739 */ 2740 int mGood = INVALID; 2741 /* 2742 * Thresholds, A signal value of bad strength to leave. 2743 */ 2744 int mBad = INVALID; 2745 /* 2746 * Thresholds, A signal value of worst strength to enter. 2747 * The worst strength is only applicable for cellular. 2748 */ 2749 int mWorst = INVALID; 2750 QnsConfigArray(int good, int bad, int worst)2751 QnsConfigArray(int good, int bad, int worst) { 2752 set(good, bad, worst); 2753 } 2754 QnsConfigArray(int good, int bad)2755 QnsConfigArray(int good, int bad) { 2756 set(good, bad, INVALID); 2757 } 2758 set(int good, int bad, int worst)2759 void set(int good, int bad, int worst) { 2760 mGood = good; 2761 mBad = bad; 2762 mWorst = worst; 2763 } 2764 2765 @Override toString()2766 public String toString() { 2767 return "QnsConfigArray{" 2768 + "Good=" 2769 + mGood 2770 + ", Bad=" 2771 + mBad 2772 + ", Worst=" 2773 + mWorst 2774 + '}'; 2775 } 2776 } 2777 2778 @VisibleForTesting 2779 static class RtpMetricsConfig { 2780 /** Maximum jitter */ 2781 final int mJitter; 2782 2783 /** RTP packet loss rate in percentage */ 2784 final int mPktLossRate; 2785 2786 /** Time interval(milliseconds) of RTP packet loss rate */ 2787 final int mPktLossTime; 2788 2789 /** No RTP interval in milliseconds */ 2790 final int mNoRtpInterval; 2791 RtpMetricsConfig(int jitter, int pktLossRate, int pktLossTime, int noRtpInterval)2792 RtpMetricsConfig(int jitter, int pktLossRate, int pktLossTime, int noRtpInterval) { 2793 this.mJitter = jitter; 2794 this.mPktLossRate = pktLossRate; 2795 this.mPktLossTime = pktLossTime; 2796 this.mNoRtpInterval = noRtpInterval; 2797 } 2798 2799 @Override toString()2800 public String toString() { 2801 return "RtpMetricsConfig{" 2802 + "mJitter=" 2803 + mJitter 2804 + ", mPktLossRate=" 2805 + mPktLossRate 2806 + ", mPktLossTime=" 2807 + mPktLossTime 2808 + ", mNoRtpInterval=" 2809 + mNoRtpInterval 2810 + '}'; 2811 } 2812 } 2813 2814 @VisibleForTesting getQnsCarrierAnspSupportConfig()2815 QnsCarrierAnspSupportConfig getQnsCarrierAnspSupportConfig() { 2816 return mAnspConfigMgr; 2817 } 2818 } 2819