1 /* 2 * Copyright (C) 2022 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.services.telephony.domainselection; 18 19 import static android.telephony.AccessNetworkConstants.AccessNetworkType.CDMA2000; 20 import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN; 21 import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN; 22 import static android.telephony.AccessNetworkConstants.AccessNetworkType.UNKNOWN; 23 import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN; 24 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_INVALID; 25 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN; 26 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 27 import static android.telephony.BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY; 28 import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_CS; 29 import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP; 30 import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP; 31 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT; 32 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY; 33 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY; 34 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY; 35 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL; 36 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT; 37 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY; 38 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY; 39 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY; 40 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY; 41 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL; 42 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL; 43 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_SCAN_TIMER_SEC_INT; 44 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT; 45 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT; 46 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT; 47 import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL; 48 import static android.telephony.CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE; 49 import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_SETTING_ENABLED; 50 import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_VALID_EID; 51 import static android.telephony.CarrierConfigManager.ImsWfc.KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL; 52 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME; 53 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING; 54 import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE; 55 import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE; 56 57 import android.annotation.NonNull; 58 import android.content.Context; 59 import android.net.ConnectivityManager; 60 import android.net.Network; 61 import android.net.NetworkCapabilities; 62 import android.net.NetworkRequest; 63 import android.os.CancellationSignal; 64 import android.os.Looper; 65 import android.os.Message; 66 import android.os.PersistableBundle; 67 import android.os.PowerManager; 68 import android.os.SystemProperties; 69 import android.telephony.AccessNetworkConstants.AccessNetworkType; 70 import android.telephony.AccessNetworkConstants.RadioAccessNetworkType; 71 import android.telephony.AccessNetworkConstants.TransportType; 72 import android.telephony.BarringInfo; 73 import android.telephony.CarrierConfigManager; 74 import android.telephony.DisconnectCause; 75 import android.telephony.DomainSelectionService; 76 import android.telephony.DomainSelectionService.SelectionAttributes; 77 import android.telephony.EmergencyRegResult; 78 import android.telephony.NetworkRegistrationInfo; 79 import android.telephony.PhoneNumberUtils; 80 import android.telephony.SubscriptionManager; 81 import android.telephony.TelephonyManager; 82 import android.telephony.TransportSelectorCallback; 83 import android.telephony.emergency.EmergencyNumber; 84 import android.telephony.ims.ImsManager; 85 import android.telephony.ims.ImsMmTelManager; 86 import android.telephony.ims.ImsReasonInfo; 87 import android.telephony.ims.ProvisioningManager; 88 import android.text.TextUtils; 89 import android.util.LocalLog; 90 91 import com.android.internal.annotations.VisibleForTesting; 92 93 import java.util.ArrayList; 94 import java.util.Arrays; 95 import java.util.HashMap; 96 import java.util.List; 97 import java.util.Map; 98 import java.util.function.IntFunction; 99 100 /** 101 * Selects the domain for emergency calling. 102 */ 103 public class EmergencyCallDomainSelector extends DomainSelectorBase 104 implements ImsStateTracker.BarringInfoListener, ImsStateTracker.ImsStateListener { 105 private static final String TAG = "DomainSelector-EmergencyCall"; 106 private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1); 107 private static final int LOG_SIZE = 50; 108 109 private static final int MSG_START_DOMAIN_SELECTION = 11; 110 @VisibleForTesting 111 public static final int MSG_NETWORK_SCAN_TIMEOUT = 12; 112 private static final int MSG_NETWORK_SCAN_RESULT = 13; 113 @VisibleForTesting 114 public static final int MSG_MAX_CELLULAR_TIMEOUT = 14; 115 116 private static final int NOT_SUPPORTED = -1; 117 118 private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE); 119 120 private static final ArrayList<String> sAllowOnlyWithSimReady = new ArrayList<>(); 121 122 static { 123 // b/177967010, JP 124 sAllowOnlyWithSimReady.add("jp"); // Japan 125 // b/198393826, DE 126 sAllowOnlyWithSimReady.add("de"); // Germany 127 // b/230443699, IN and SG 128 sAllowOnlyWithSimReady.add("in"); // India 129 sAllowOnlyWithSimReady.add("sg"); // Singapore 130 } 131 132 /** 133 * Network callback used to determine whether Wi-Fi is connected or not. 134 */ 135 private ConnectivityManager.NetworkCallback mNetworkCallback = 136 new ConnectivityManager.NetworkCallback() { 137 @Override 138 public void onAvailable(Network network) { 139 logi("onAvailable: " + network); 140 mWiFiAvailable = true; 141 } 142 143 @Override 144 public void onLost(Network network) { 145 logi("onLost: " + network); 146 mWiFiAvailable = false; 147 } 148 149 @Override 150 public void onUnavailable() { 151 logi("onUnavailable"); 152 mWiFiAvailable = false; 153 } 154 }; 155 156 private boolean mIsEmergencyBarred; 157 private boolean mImsRegistered; 158 private boolean mIsVoiceCapable; 159 private boolean mBarringInfoReceived; 160 private boolean mImsRegStateReceived; 161 private boolean mMmTelCapabilitiesReceived; 162 private int mVoWifiTrialCount = 0; 163 164 private @RadioAccessNetworkType int mCsNetworkType = UNKNOWN; 165 private @RadioAccessNetworkType int mPsNetworkType = UNKNOWN; 166 private @RadioAccessNetworkType int mLastNetworkType = UNKNOWN; 167 private @TransportType int mLastTransportType = TRANSPORT_TYPE_INVALID; 168 private @DomainSelectionService.EmergencyScanType int mScanType; 169 private @RadioAccessNetworkType List<Integer> mLastPreferredNetworks; 170 private boolean mIsTestEmergencyNumber; 171 172 private CancellationSignal mCancelSignal; 173 174 private @RadioAccessNetworkType int[] mImsRatsConfig; 175 private @RadioAccessNetworkType int[] mCsRatsConfig; 176 private @RadioAccessNetworkType int[] mImsRoamRatsConfig; 177 private @RadioAccessNetworkType int[] mCsRoamRatsConfig; 178 private @CarrierConfigManager.ImsEmergency.EmergencyDomain int[] mDomainPreference; 179 private @CarrierConfigManager.ImsEmergency.EmergencyDomain int[] mDomainPreferenceRoam; 180 private List<String> mCdmaPreferredNumbers; 181 private boolean mPreferImsWhenCallsOnCs; 182 private int mVoWifiRequiresCondition; 183 private boolean mIsMonitoringConnectivity; 184 private boolean mWiFiAvailable; 185 private int mScanTimeout; 186 private int mMaxCellularTimeout; 187 private int mMaxNumOfVoWifiTries; 188 private boolean mVoWifiOverEmergencyPdn; 189 private @CarrierConfigManager.ImsEmergency.EmergencyScanType int mPreferredNetworkScanType; 190 private int mCallSetupTimerOnCurrentRat; 191 private boolean mRequiresImsRegistration; 192 private boolean mRequiresVoLteEnabled; 193 private boolean mLtePreferredAfterNrFailure; 194 private boolean mTryCsWhenPsFails; 195 private boolean mTryEpsFallback; 196 private int mModemCount; 197 198 /** Indicates whether this instance is deactivated. */ 199 private boolean mDestroyed = false; 200 /** Indicates whether emergency network scan is requested. */ 201 private boolean mIsScanRequested = false; 202 /** Indicates whether selected domain has been notified. */ 203 private boolean mDomainSelected = false; 204 /** Indicates whether the cross sim redialing timer has expired. */ 205 private boolean mCrossStackTimerExpired = false; 206 /** Indicates whether max cellular timer expired. */ 207 private boolean mMaxCellularTimerExpired = false; 208 209 /** 210 * Indicates whether {@link #selectDomain(SelectionAttributes, TransportSelectionCallback)} 211 * is called or not. 212 */ 213 private boolean mDomainSelectionRequested = false; 214 215 private final PowerManager.WakeLock mPartialWakeLock; 216 private final CrossSimRedialingController mCrossSimRedialingController; 217 218 /** Constructor. */ EmergencyCallDomainSelector(Context context, int slotId, int subId, @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker, @NonNull DestroyListener destroyListener, @NonNull CrossSimRedialingController csrController)219 public EmergencyCallDomainSelector(Context context, int slotId, int subId, 220 @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker, 221 @NonNull DestroyListener destroyListener, 222 @NonNull CrossSimRedialingController csrController) { 223 super(context, slotId, subId, looper, imsStateTracker, destroyListener, TAG); 224 225 mImsStateTracker.addBarringInfoListener(this); 226 mImsStateTracker.addImsStateListener(this); 227 228 PowerManager pm = context.getSystemService(PowerManager.class); 229 mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 230 231 mCrossSimRedialingController = csrController; 232 acquireWakeLock(); 233 } 234 235 @Override handleMessage(Message msg)236 public void handleMessage(Message msg) { 237 if (mDestroyed) return; 238 239 switch(msg.what) { 240 case MSG_START_DOMAIN_SELECTION: 241 startDomainSelection(); 242 break; 243 244 case MSG_NETWORK_SCAN_TIMEOUT: 245 handleNetworkScanTimeout(); 246 break; 247 248 case MSG_NETWORK_SCAN_RESULT: 249 handleScanResult((EmergencyRegResult) msg.obj); 250 break; 251 252 case MSG_MAX_CELLULAR_TIMEOUT: 253 handleMaxCellularTimeout(); 254 break; 255 256 default: 257 super.handleMessage(msg); 258 break; 259 } 260 } 261 262 /** 263 * Handles the scan result. 264 * 265 * @param result The scan result. 266 */ handleScanResult(EmergencyRegResult result)267 private void handleScanResult(EmergencyRegResult result) { 268 logi("handleScanResult result=" + result); 269 270 if (mLastTransportType == TRANSPORT_TYPE_WLAN) { 271 logi("handleScanResult timer expired, WLAN has been selected, ignore stale result"); 272 return; 273 } 274 275 // Detected the country and found that emergency calls are not allowed with this slot. 276 if (!allowEmergencyCalls(result)) { 277 terminateSelectionPermanentlyForSlot(); 278 return; 279 } 280 281 if (result.getAccessNetwork() == UNKNOWN) { 282 if ((mPreferredNetworkScanType == SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE) 283 && (mScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) { 284 mScanType = DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE; 285 mWwanSelectorCallback.onRequestEmergencyNetworkScan( 286 mLastPreferredNetworks, mScanType, mCancelSignal, 287 (regResult) -> { 288 logi("requestScan-onComplete"); 289 sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, regResult)); 290 }); 291 } else { 292 // Continuous scan, do not start a new timer. 293 requestScan(false); 294 } 295 return; 296 } 297 298 removeMessages(MSG_NETWORK_SCAN_TIMEOUT); 299 onWwanNetworkTypeSelected(getAccessNetworkType(result)); 300 mCancelSignal = null; 301 } 302 303 /** 304 * Determines the scanned network type. 305 * 306 * @param result The result of network scan. 307 * @return The selected network type. 308 */ getAccessNetworkType(EmergencyRegResult result)309 private @RadioAccessNetworkType int getAccessNetworkType(EmergencyRegResult result) { 310 int accessNetworkType = result.getAccessNetwork(); 311 if (accessNetworkType != EUTRAN) return accessNetworkType; 312 313 int regState = result.getRegState(); 314 int domain = result.getDomain(); 315 316 // Emergency is not supported with LTE, but CSFB is possible. 317 if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING) 318 && (domain == NetworkRegistrationInfo.DOMAIN_CS)) { 319 logi("getAccessNetworkType emergency not supported but CSFB is possible"); 320 accessNetworkType = UTRAN; 321 } 322 323 return accessNetworkType; 324 } 325 326 @Override cancelSelection()327 public void cancelSelection() { 328 logi("cancelSelection"); 329 finishSelection(); 330 } 331 332 @Override reselectDomain(SelectionAttributes attr)333 public void reselectDomain(SelectionAttributes attr) { 334 logi("reselectDomain attr=" + attr); 335 mSelectionAttributes = attr; 336 post(() -> { reselectDomain(); }); 337 } 338 reselectDomain()339 private void reselectDomain() { 340 logi("reselectDomain tryCsWhenPsFails=" + mTryCsWhenPsFails); 341 342 int cause = mSelectionAttributes.getCsDisconnectCause(); 343 mCrossSimRedialingController.notifyCallFailure(cause); 344 345 // TODO(b/258112541) make EMERGENCY_PERM_FAILURE and EMERGENCY_TEMP_FAILURE public api 346 if (cause == EMERGENCY_PERM_FAILURE 347 || cause == EMERGENCY_TEMP_FAILURE) { 348 logi("reselectDomain should redial on the other subscription"); 349 terminateSelectionForCrossSimRedialing(cause == EMERGENCY_PERM_FAILURE); 350 return; 351 } 352 353 if (mCrossStackTimerExpired) { 354 logi("reselectDomain cross stack timer expired"); 355 terminateSelectionForCrossSimRedialing(false); 356 return; 357 } 358 359 if (mIsTestEmergencyNumber) { 360 selectDomainForTestEmergencyNumber(); 361 return; 362 } 363 364 if (mTryCsWhenPsFails) { 365 mTryCsWhenPsFails = false; 366 // Initial state was CSFB available and dial PS failed. 367 // Dial CS for CSFB instead of scanning with CS preferred network list. 368 logi("reselectDomain tryCs=" + accessNetworkTypeToString(mCsNetworkType)); 369 if (mCsNetworkType != UNKNOWN) { 370 onWwanNetworkTypeSelected(mCsNetworkType); 371 return; 372 } 373 } 374 375 if (mMaxCellularTimerExpired) { 376 if (mLastTransportType == TRANSPORT_TYPE_WWAN 377 && maybeDialOverWlan()) { 378 // Cellular call failed and max cellular search timer expired, so redial on Wi-Fi. 379 // If this VoWi-Fi fails, the timer shall be restarted on next reselectDomain(). 380 return; 381 } else if (mLastTransportType == TRANSPORT_TYPE_WLAN) { 382 // Since VoWi-Fi failed, allow for requestScan to restart max cellular timer. 383 mMaxCellularTimerExpired = false; 384 } 385 } 386 387 if (mLastTransportType == TRANSPORT_TYPE_WLAN) { 388 // Dialing over Wi-Fi failed. Try scanning cellular networks. 389 onWwanSelected(this::reselectDomainInternal); 390 return; 391 } 392 393 requestScan(true); 394 mDomainSelected = false; 395 } 396 reselectDomainInternal()397 private void reselectDomainInternal() { 398 post(() -> { 399 requestScan(true, false, true); 400 mDomainSelected = false; 401 }); 402 } 403 404 @Override finishSelection()405 public void finishSelection() { 406 logi("finishSelection"); 407 destroy(); 408 } 409 410 @Override onBarringInfoUpdated(BarringInfo barringInfo)411 public void onBarringInfoUpdated(BarringInfo barringInfo) { 412 if (mDestroyed) return; 413 414 mBarringInfoReceived = true; 415 BarringInfo.BarringServiceInfo serviceInfo = 416 barringInfo.getBarringServiceInfo(BARRING_SERVICE_TYPE_EMERGENCY); 417 mIsEmergencyBarred = serviceInfo.isBarred(); 418 logi("onBarringInfoUpdated emergencyBarred=" + mIsEmergencyBarred 419 + ", serviceInfo=" + serviceInfo); 420 selectDomain(); 421 } 422 423 @Override selectDomain(SelectionAttributes attr, TransportSelectorCallback cb)424 public void selectDomain(SelectionAttributes attr, TransportSelectorCallback cb) { 425 logi("selectDomain attr=" + attr); 426 mTransportSelectorCallback = cb; 427 mSelectionAttributes = attr; 428 mIsTestEmergencyNumber = isTestEmergencyNumber(attr.getNumber()); 429 430 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 431 mModemCount = tm.getActiveModemCount(); 432 433 sendEmptyMessage(MSG_START_DOMAIN_SELECTION); 434 } 435 startDomainSelection()436 private void startDomainSelection() { 437 logi("startDomainSelection modemCount=" + mModemCount); 438 updateCarrierConfiguration(); 439 mDomainSelectionRequested = true; 440 startCrossStackTimer(); 441 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 442 selectDomain(); 443 } else { 444 logi("startDomainSelection invalid subId"); 445 onImsRegistrationStateChanged(); 446 onImsMmTelCapabilitiesChanged(); 447 } 448 } 449 450 @Override onImsMmTelFeatureAvailableChanged()451 public void onImsMmTelFeatureAvailableChanged() { 452 // DOMAIN_CS shall be selected when ImsService is not available. 453 // TODO(b/258289015) Recover the temporary failure in ImsService connection. 454 } 455 456 @Override onImsRegistrationStateChanged()457 public void onImsRegistrationStateChanged() { 458 mImsRegStateReceived = true; 459 mImsRegistered = mImsStateTracker.isImsRegistered(); 460 logi("onImsRegistrationStateChanged " + mImsRegistered); 461 selectDomain(); 462 } 463 464 @Override onImsMmTelCapabilitiesChanged()465 public void onImsMmTelCapabilitiesChanged() { 466 mMmTelCapabilitiesReceived = true; 467 mIsVoiceCapable = mImsStateTracker.isImsVoiceCapable(); 468 logi("onImsMmTelCapabilitiesChanged " + mIsVoiceCapable); 469 selectDomain(); 470 } 471 472 /** 473 * Caches the configuration. 474 */ updateCarrierConfiguration()475 private void updateCarrierConfiguration() { 476 CarrierConfigManager configMgr = mContext.getSystemService(CarrierConfigManager.class); 477 PersistableBundle b = configMgr.getConfigForSubId(getSubId()); 478 if (b == null) { 479 b = CarrierConfigManager.getDefaultConfig(); 480 } 481 482 mImsRatsConfig = 483 b.getIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY); 484 mImsRoamRatsConfig = b.getIntArray( 485 KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY); 486 if (!SubscriptionManager.isValidSubscriptionId(getSubId())) { 487 // Default configuration includes only EUTRAN . In case of no SIM, add NGRAN. 488 mImsRatsConfig = new int[] { EUTRAN, NGRAN }; 489 mImsRoamRatsConfig = new int[] { EUTRAN, NGRAN }; 490 } 491 492 mCsRatsConfig = 493 b.getIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY); 494 mCsRoamRatsConfig = b.getIntArray( 495 KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY); 496 mDomainPreference = b.getIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY); 497 mDomainPreferenceRoam = b.getIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY); 498 mPreferImsWhenCallsOnCs = b.getBoolean( 499 KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL); 500 mVoWifiRequiresCondition = b.getInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT); 501 mScanTimeout = b.getInt(KEY_EMERGENCY_SCAN_TIMER_SEC_INT) * 1000; 502 mMaxCellularTimeout = b.getInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT) * 1000; 503 mMaxNumOfVoWifiTries = b.getInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT); 504 mVoWifiOverEmergencyPdn = b.getBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL); 505 mPreferredNetworkScanType = b.getInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT); 506 mCallSetupTimerOnCurrentRat = b.getInt( 507 KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT) * 1000; 508 mRequiresImsRegistration = b.getBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL); 509 mRequiresVoLteEnabled = b.getBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL); 510 mLtePreferredAfterNrFailure = b.getBoolean( 511 KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL); 512 String[] numbers = b.getStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY); 513 514 if (mImsRatsConfig == null) mImsRatsConfig = new int[0]; 515 if (mCsRatsConfig == null) mCsRatsConfig = new int[0]; 516 if (mImsRoamRatsConfig == null) mImsRoamRatsConfig = new int[0]; 517 if (mCsRoamRatsConfig == null) mCsRoamRatsConfig = new int[0]; 518 if (mDomainPreference == null) mDomainPreference = new int[0]; 519 if (mDomainPreferenceRoam == null) mDomainPreferenceRoam = new int[0]; 520 if (numbers == null) numbers = new String[0]; 521 522 logi("updateCarrierConfiguration " 523 + "imsRats=" + arrayToString(mImsRatsConfig, 524 EmergencyCallDomainSelector::accessNetworkTypeToString) 525 + ", csRats=" + arrayToString(mCsRatsConfig, 526 EmergencyCallDomainSelector::accessNetworkTypeToString) 527 + ", imsRoamRats=" + arrayToString(mImsRoamRatsConfig, 528 EmergencyCallDomainSelector::accessNetworkTypeToString) 529 + ", csRoamRats=" + arrayToString(mCsRoamRatsConfig, 530 EmergencyCallDomainSelector::accessNetworkTypeToString) 531 + ", domainPref=" + arrayToString(mDomainPreference, 532 EmergencyCallDomainSelector::domainPreferenceToString) 533 + ", domainPrefRoam=" + arrayToString(mDomainPreferenceRoam, 534 EmergencyCallDomainSelector::domainPreferenceToString) 535 + ", preferImsOnCs=" + mPreferImsWhenCallsOnCs 536 + ", voWifiRequiresCondition=" + mVoWifiRequiresCondition 537 + ", scanTimeout=" + mScanTimeout 538 + ", maxCellularTimeout=" + mMaxCellularTimeout 539 + ", maxNumOfVoWifiTries=" + mMaxNumOfVoWifiTries 540 + ", voWifiOverEmergencyPdn=" + mVoWifiOverEmergencyPdn 541 + ", preferredScanType=" + carrierConfigNetworkScanTypeToString( 542 mPreferredNetworkScanType) 543 + ", callSetupTimer=" + mCallSetupTimerOnCurrentRat 544 + ", requiresImsReg=" + mRequiresImsRegistration 545 + ", requiresVoLteEnabled=" + mRequiresVoLteEnabled 546 + ", ltePreferredAfterNr=" + mLtePreferredAfterNrFailure 547 + ", cdmaPreferredNumbers=" + arrayToString(numbers)); 548 549 mCdmaPreferredNumbers = Arrays.asList(numbers); 550 551 if ((mPreferredNetworkScanType == CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE) 552 || (mPreferredNetworkScanType 553 == SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE)) { 554 mScanType = DomainSelectionService.SCAN_TYPE_FULL_SERVICE; 555 } else { 556 mScanType = DomainSelectionService.SCAN_TYPE_NO_PREFERENCE; 557 } 558 } 559 selectDomain()560 private void selectDomain() { 561 // State updated right after creation. 562 if (!mDomainSelectionRequested) return; 563 564 // Emergency network scan requested has not been completed. 565 if (mIsScanRequested) return; 566 567 // Domain selection completed, {@link #reselectDomain()} will restart domain selection. 568 if (mDomainSelected) return; 569 570 if (!mBarringInfoReceived || !mImsRegStateReceived || !mMmTelCapabilitiesReceived) { 571 logi("selectDomain not received" 572 + " BarringInfo, IMS registration state, or MMTEL capabilities"); 573 return; 574 } 575 576 if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegResult())) { 577 // Detected the country and found that emergency calls are not allowed with this slot. 578 terminateSelectionPermanentlyForSlot(); 579 return; 580 } 581 582 if (isWifiPreferred()) { 583 onWlanSelected(); 584 return; 585 } 586 587 onWwanSelected(this::selectDomainInternal); 588 } 589 selectDomainInternal()590 private void selectDomainInternal() { 591 post(this::selectDomainFromInitialState); 592 } 593 selectDomainFromInitialState()594 private void selectDomainFromInitialState() { 595 if (mIsTestEmergencyNumber) { 596 selectDomainForTestEmergencyNumber(); 597 return; 598 } 599 600 boolean csInService = isCsInService(); 601 boolean psInService = isPsInService(); 602 603 if (!csInService && !psInService) { 604 mPsNetworkType = getSelectablePsNetworkType(false); 605 logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType)); 606 if (mPsNetworkType == UNKNOWN) { 607 requestScan(true); 608 } else { 609 onWwanNetworkTypeSelected(mPsNetworkType); 610 } 611 return; 612 } 613 614 // Domain selection per 3GPP TS 23.167 Table H.1. 615 // PS is preferred in case selection between CS and PS is implementation option. 616 mCsNetworkType = UNKNOWN; 617 mPsNetworkType = UNKNOWN; 618 if (csInService) mCsNetworkType = getSelectableCsNetworkType(); 619 if (psInService) mPsNetworkType = getSelectablePsNetworkType(true); 620 621 boolean csAvailable = mCsNetworkType != UNKNOWN; 622 boolean psAvailable = mPsNetworkType != UNKNOWN; 623 624 logi("selectDomain CS={" + csInService + ", " + accessNetworkTypeToString(mCsNetworkType) 625 + "}, PS={" + psInService + ", " + accessNetworkTypeToString(mPsNetworkType) + "}"); 626 if (csAvailable && psAvailable) { 627 if (mPreferImsWhenCallsOnCs || isImsRegisteredWithVoiceCapability()) { 628 mTryCsWhenPsFails = true; 629 onWwanNetworkTypeSelected(mPsNetworkType); 630 } else if (isDeactivatedSim()) { 631 // Deactivated SIM but PS is in service and supports emergency calls. 632 onWwanNetworkTypeSelected(mPsNetworkType); 633 } else { 634 onWwanNetworkTypeSelected(mCsNetworkType); 635 } 636 } else if (psAvailable) { 637 mTryEpsFallback = (mPsNetworkType == NGRAN) && isEpsFallbackAvailable(); 638 if (!mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) { 639 onWwanNetworkTypeSelected(mPsNetworkType); 640 } else if (isDeactivatedSim()) { 641 // Deactivated SIM but PS is in service and supports emergency calls. 642 onWwanNetworkTypeSelected(mPsNetworkType); 643 } else { 644 // Carrier configuration requires IMS registration for emergency services over PS, 645 // but not registered. Try CS emergency call. 646 mTryEpsFallback = false; 647 requestScan(true, true); 648 } 649 } else if (csAvailable) { 650 onWwanNetworkTypeSelected(mCsNetworkType); 651 } else { 652 // PS is in service but not supports emergency calls. 653 if (mRequiresImsRegistration && !isImsRegisteredWithVoiceCapability()) { 654 // Carrier configuration requires IMS registration for emergency services over PS, 655 // but not registered. Try CS emergency call. 656 requestScan(true, true); 657 } else { 658 mTryEpsFallback = isEpsFallbackAvailable(); 659 requestScan(true); 660 } 661 } 662 } 663 664 /** 665 * Requests network scan. 666 * 667 * @param startVoWifiTimer Indicates whether a VoWifi timer will be started. 668 */ requestScan(boolean startVoWifiTimer)669 private void requestScan(boolean startVoWifiTimer) { 670 requestScan(startVoWifiTimer, false); 671 } 672 673 /** 674 * Requests network scan. 675 * 676 * @param startVoWifiTimer Indicates whether a VoWifi timer will be started. 677 * @param csPreferred Indicates whether CS preferred scan is requested. 678 */ requestScan(boolean startVoWifiTimer, boolean csPreferred)679 private void requestScan(boolean startVoWifiTimer, boolean csPreferred) { 680 requestScan(startVoWifiTimer, csPreferred, false); 681 } 682 683 /** 684 * Requests network scan. 685 * 686 * @param startVoWifiTimer Indicates whether a VoWifi timer will be started. 687 * @param csPreferred Indicates whether CS preferred scan is requested. 688 * @param wifiFailed Indicates dialing over Wi-Fi has failed. 689 */ requestScan(boolean startVoWifiTimer, boolean csPreferred, boolean wifiFailed)690 private void requestScan(boolean startVoWifiTimer, boolean csPreferred, boolean wifiFailed) { 691 logi("requestScan timer=" + startVoWifiTimer + ", csPreferred=" + csPreferred 692 + ", wifiFailed=" + wifiFailed); 693 694 mCancelSignal = new CancellationSignal(); 695 // In case dialing over Wi-Fi has failed, do not the change the domain preference. 696 if (!wifiFailed) { 697 mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback, 698 !startVoWifiTimer); 699 } 700 mTryEpsFallback = false; 701 702 if (isInRoaming() 703 && (mPreferredNetworkScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) { 704 // FULL_SERVICE only preference is available only when not in roaming. 705 mScanType = DomainSelectionService.SCAN_TYPE_NO_PREFERENCE; 706 } 707 708 mIsScanRequested = true; 709 mWwanSelectorCallback.onRequestEmergencyNetworkScan( 710 mLastPreferredNetworks, mScanType, mCancelSignal, 711 (result) -> { 712 logi("requestScan-onComplete"); 713 sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, result)); 714 }); 715 716 if (startVoWifiTimer && SubscriptionManager.isValidSubscriptionId(getSubId())) { 717 if (isEmcOverWifiSupported() 718 && mScanTimeout > 0 && mVoWifiTrialCount < mMaxNumOfVoWifiTries) { 719 logi("requestScan start scan timer"); 720 // remove any pending timers. 721 removeMessages(MSG_NETWORK_SCAN_TIMEOUT); 722 sendEmptyMessageDelayed(MSG_NETWORK_SCAN_TIMEOUT, mScanTimeout); 723 registerForConnectivityChanges(); 724 } 725 } 726 if (!mMaxCellularTimerExpired && !hasMessages(MSG_MAX_CELLULAR_TIMEOUT)) { 727 startMaxCellularTimer(); 728 } 729 } 730 731 /** 732 * Gets the list of preferred network type for the new scan request. 733 * 734 * @param csPreferred Indicates whether CS preferred scan is requested. 735 * @param tryEpsFallback Indicates whether scan requested for EPS fallback. 736 * @param lastScanFailed Indicates whether this a scan request due to the failure of last scan 737 * request. 738 * @return The list of preferred network types. 739 */ 740 @VisibleForTesting getNextPreferredNetworks(boolean csPreferred, boolean tryEpsFallback, boolean lastScanFailed)741 public @RadioAccessNetworkType List<Integer> getNextPreferredNetworks(boolean csPreferred, 742 boolean tryEpsFallback, boolean lastScanFailed) { 743 if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) { 744 // Emergency call over IMS is not supported. 745 logi("getNextPreferredNetworks VoLte setting is not enabled."); 746 return generatePreferredNetworks(getCsNetworkTypeConfiguration()); 747 } 748 749 List<Integer> preferredNetworks = new ArrayList<>(); 750 751 List<Integer> domains = getDomainPreference(); 752 int psPriority = domains.indexOf(DOMAIN_PS_3GPP); 753 int csPriority = domains.indexOf(DOMAIN_CS); 754 logi("getNextPreferredNetworks psPriority=" + psPriority + ", csPriority=" + csPriority 755 + ", csPreferred=" + csPreferred + ", epsFallback=" + tryEpsFallback 756 + ", lastNetworkType=" + accessNetworkTypeToString(mLastNetworkType)); 757 758 if (!csPreferred && (mLastNetworkType == UNKNOWN || tryEpsFallback)) { 759 // Generate the list per the domain preference. 760 761 if (psPriority == NOT_SUPPORTED && csPriority == NOT_SUPPORTED) { 762 // should not reach here. However, to avoid unexpected problems. 763 preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(), 764 getImsNetworkTypeConfiguration()); 765 } else if (psPriority == NOT_SUPPORTED && csPriority > NOT_SUPPORTED) { 766 // CS networks only. 767 preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration()); 768 } else if (psPriority > NOT_SUPPORTED && csPriority == NOT_SUPPORTED) { 769 // PS networks only. 770 preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration()); 771 } else if (psPriority < csPriority) { 772 // PS preferred. 773 preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(), 774 getCsNetworkTypeConfiguration()); 775 } else { 776 // CS preferred. 777 preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(), 778 getImsNetworkTypeConfiguration()); 779 } 780 781 // Make NGRAN have the lowest priority 782 if (tryEpsFallback && preferredNetworks.contains(NGRAN)) { 783 preferredNetworks.remove(Integer.valueOf(NGRAN)); 784 preferredNetworks.add(NGRAN); 785 } 786 } else if (csPreferred || mLastNetworkType == EUTRAN || mLastNetworkType == NGRAN) { 787 if (!csPreferred && mLastNetworkType == NGRAN && mLtePreferredAfterNrFailure) { 788 // LTE is preferred after dialing over NR failed. 789 List<Integer> imsRats = getImsNetworkTypeConfiguration(); 790 imsRats.remove(Integer.valueOf(NGRAN)); 791 preferredNetworks = generatePreferredNetworks(imsRats, 792 getCsNetworkTypeConfiguration()); 793 } else if (csPriority > NOT_SUPPORTED) { 794 // PS tried, generate the list with CS preferred. 795 preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(), 796 getImsNetworkTypeConfiguration()); 797 } else { 798 // CS not suppored. 799 preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration()); 800 } 801 } else { 802 // CS tried, generate the list with PS preferred. 803 if (psPriority > NOT_SUPPORTED) { 804 preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(), 805 getCsNetworkTypeConfiguration()); 806 } else { 807 // PS not suppored. 808 preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration()); 809 } 810 } 811 812 // There can be cases that dialing IMS call failed but the modem doesn't know this 813 // situation with some vendor solutions. For example, dialing failure due to the 814 // emergency registration failure. 815 // Remove the current RAT from the scan list to avoid modem select current PLMN. 816 // If the scan fails, the next scan will include this RAT again. 817 // 818 // TODO (b/278183420) Replace this with a better solution by adding indication 819 // of call setup failure to the scan request. 820 ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause(); 821 if (!lastScanFailed && reasonInfo != null 822 && reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED) { 823 logi("getNextPreferredNetworks remove " + mLastNetworkType); 824 if (preferredNetworks.size() > 1) { 825 preferredNetworks.remove(Integer.valueOf(mLastNetworkType)); 826 } 827 } 828 829 return preferredNetworks; 830 } 831 generatePreferredNetworks(List<Integer>....lists)832 private @RadioAccessNetworkType List<Integer> generatePreferredNetworks(List<Integer>...lists) { 833 List<Integer> preferredNetworks = new ArrayList<>(); 834 for (List<Integer> list : lists) { 835 preferredNetworks.addAll(list); 836 } 837 838 return preferredNetworks; 839 } 840 handleMaxCellularTimeout()841 private void handleMaxCellularTimeout() { 842 logi("handleMaxCellularTimeout"); 843 if (mVoWifiTrialCount >= mMaxNumOfVoWifiTries) { 844 logi("handleMaxCellularTimeout already tried maximum"); 845 return; 846 } 847 848 mMaxCellularTimerExpired = true; 849 850 if (mDomainSelected) { 851 // Dialing is already requested. 852 logi("handleMaxCellularTimeout wait for reselectDomain"); 853 return; 854 } 855 856 if (!maybeDialOverWlan()) { 857 logd("handleMaxCellularTimeout VoWi-Fi is not available"); 858 } 859 } 860 handleNetworkScanTimeout()861 private void handleNetworkScanTimeout() { 862 logi("handleNetworkScanTimeout"); 863 maybeDialOverWlan(); 864 } 865 maybeDialOverWlan()866 private boolean maybeDialOverWlan() { 867 logi("maybeDialOverWlan overEmergencyPdn=" + mVoWifiOverEmergencyPdn 868 + ", wifiAvailable=" + mWiFiAvailable); 869 boolean available = mWiFiAvailable; 870 if (mVoWifiOverEmergencyPdn) { 871 // SOS APN 872 if (!available && isImsRegisteredOverCrossSim()) { 873 available = true; 874 } 875 if (available) { 876 switch (mVoWifiRequiresCondition) { 877 case VOWIFI_REQUIRES_SETTING_ENABLED: 878 available = isWifiCallingSettingEnabled(); 879 break; 880 case VOWIFI_REQUIRES_VALID_EID: 881 available = isWifiCallingActivated(); 882 break; 883 default: 884 break; 885 } 886 } 887 } else { 888 // IMS APN. When IMS is already registered over Wi-Fi. 889 available = isImsRegisteredWithVoiceCapability() && isImsRegisteredOverWifi(); 890 } 891 892 logi("maybeDialOverWlan VoWi-Fi available=" + available); 893 if (available) { 894 if (mCancelSignal != null) { 895 mCancelSignal.cancel(); 896 mCancelSignal = null; 897 } 898 onWlanSelected(); 899 } 900 901 return available; 902 } 903 904 /** 905 * Determines whether CS is in service. 906 * 907 * @return {@code true} if CS is in service. 908 */ isCsInService()909 private boolean isCsInService() { 910 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 911 if (regResult == null) return false; 912 913 int regState = regResult.getRegState(); 914 int domain = regResult.getDomain(); 915 916 if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING) 917 && ((domain & NetworkRegistrationInfo.DOMAIN_CS) > 0)) { 918 return true; 919 } 920 921 return false; 922 } 923 924 /** 925 * Determines the network type of the circuit-switched(CS) network. 926 * 927 * @return The network type of the CS network. 928 */ getSelectableCsNetworkType()929 private @RadioAccessNetworkType int getSelectableCsNetworkType() { 930 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 931 logi("getSelectableCsNetworkType regResult=" + regResult); 932 if (regResult == null) return UNKNOWN; 933 934 int accessNetwork = regResult.getAccessNetwork(); 935 936 List<Integer> ratList = getCsNetworkTypeConfiguration(); 937 if (ratList.contains(accessNetwork)) { 938 return accessNetwork; 939 } 940 941 if ((regResult.getAccessNetwork() == EUTRAN) 942 && ((regResult.getDomain() & NetworkRegistrationInfo.DOMAIN_CS) > 0)) { 943 if (ratList.contains(UTRAN)) return UTRAN; 944 } 945 946 return UNKNOWN; 947 } 948 949 /** 950 * Determines whether PS is in service. 951 * 952 * @return {@code true} if PS is in service. 953 */ isPsInService()954 private boolean isPsInService() { 955 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 956 if (regResult == null) return false; 957 958 int regState = regResult.getRegState(); 959 int domain = regResult.getDomain(); 960 961 if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING) 962 && ((domain & NetworkRegistrationInfo.DOMAIN_PS) > 0)) { 963 return true; 964 } 965 966 return false; 967 } 968 969 /** 970 * Determines the network type supporting emergency services over packet-switched(PS) network. 971 * 972 * @param inService Indicates whether PS is IN_SERVICE state. 973 * @return The network type if the network supports emergency services over PS network. 974 */ getSelectablePsNetworkType(boolean inService)975 private @RadioAccessNetworkType int getSelectablePsNetworkType(boolean inService) { 976 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 977 logi("getSelectablePsNetworkType regResult=" + regResult); 978 if (regResult == null) return UNKNOWN; 979 if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) { 980 // Emergency call over IMS is not supported. 981 logi("getSelectablePsNetworkType VoLte setting is not enabled."); 982 return UNKNOWN; 983 } 984 985 int accessNetwork = regResult.getAccessNetwork(); 986 List<Integer> ratList = getImsNetworkTypeConfiguration(); 987 if (ratList.contains(accessNetwork)) { 988 if (mIsEmergencyBarred) { 989 logi("getSelectablePsNetworkType barred"); 990 return UNKNOWN; 991 } 992 if (accessNetwork == NGRAN) { 993 return (regResult.getNwProvidedEmc() > 0 && regResult.isVopsSupported()) 994 ? NGRAN : UNKNOWN; 995 } else if (accessNetwork == EUTRAN) { 996 return (regResult.isEmcBearerSupported() 997 && (regResult.isVopsSupported() || !inService)) 998 ? EUTRAN : UNKNOWN; 999 } 1000 } 1001 1002 return UNKNOWN; 1003 } 1004 isEpsFallbackAvailable()1005 private boolean isEpsFallbackAvailable() { 1006 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 1007 if (regResult == null) return false; 1008 1009 List<Integer> ratList = getImsNetworkTypeConfiguration(); 1010 if (ratList.contains(EUTRAN)) { 1011 return (regResult.getNwProvidedEmf() > 0); 1012 } 1013 return false; 1014 } 1015 1016 /** 1017 * Determines whether the SIM is a deactivated one. 1018 * 1019 * @return {@code true} if the SIM is a deactivated one. 1020 */ isDeactivatedSim()1021 private boolean isDeactivatedSim() { 1022 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1023 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1024 tm = tm.createForSubscriptionId(getSubId()); 1025 int state = tm.getDataActivationState(); 1026 logi("isDeactivatedSim state=" + state); 1027 return (state == TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED); 1028 } 1029 return false; 1030 } 1031 1032 /** 1033 * Determines whether emergency call over Wi-Fi is allowed. 1034 * 1035 * @return {@code true} if emergency call over Wi-Fi allowed. 1036 */ isEmcOverWifiSupported()1037 private boolean isEmcOverWifiSupported() { 1038 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1039 List<Integer> domains = getDomainPreference(); 1040 boolean ret = domains.contains(DOMAIN_PS_NON_3GPP); 1041 logi("isEmcOverWifiSupported " + ret); 1042 return ret; 1043 } else { 1044 logi("isEmcOverWifiSupported invalid subId"); 1045 } 1046 return false; 1047 } 1048 1049 /** 1050 * Determines whether Wi-Fi is preferred when IMS registered over Wi-Fi. 1051 * 1052 * @return {@code true} if Wi-Fi is preferred when IMS registered over Wi-Fi. 1053 */ isWifiPreferred()1054 private boolean isWifiPreferred() { 1055 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1056 List<Integer> domains = getDomainPreference(); 1057 int priority = domains.indexOf(DOMAIN_PS_NON_3GPP); 1058 logi("isWifiPreferred priority=" + priority); 1059 1060 if ((priority == 0) 1061 && isImsRegisteredWithVoiceCapability() 1062 && isImsRegisteredOverWifi()) { 1063 logi("isWifiPreferred try emergency call over Wi-Fi"); 1064 return true; 1065 } 1066 } 1067 1068 return false; 1069 } 1070 isAdvancedCallingSettingEnabled()1071 private boolean isAdvancedCallingSettingEnabled() { 1072 try { 1073 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1074 ImsManager imsMngr = mContext.getSystemService(ImsManager.class); 1075 ImsMmTelManager mmTelManager = imsMngr.getImsMmTelManager(getSubId()); 1076 boolean result = mmTelManager.isAdvancedCallingSettingEnabled(); 1077 logi("isAdvancedCallingSettingEnabled " + result); 1078 return result; 1079 } 1080 } catch (Exception e) { 1081 logi("isAdvancedCallingSettingEnabled e=" + e); 1082 } 1083 return true; 1084 } 1085 isWifiCallingActivated()1086 private boolean isWifiCallingActivated() { 1087 try { 1088 ImsManager imsMngr = mContext.getSystemService(ImsManager.class); 1089 ProvisioningManager pm = imsMngr.getProvisioningManager(getSubId()); 1090 String eid = pm.getProvisioningStringValue( 1091 ProvisioningManager.KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID); 1092 boolean activated = (!TextUtils.isEmpty(eid)) && (!TextUtils.equals("0", eid)); 1093 logi("isWifiCallingActivated " + activated); 1094 return activated; 1095 } catch (Exception e) { 1096 logi("isWifiCallingActivated e=" + e); 1097 } 1098 return false; 1099 } 1100 isWifiCallingSettingEnabled()1101 private boolean isWifiCallingSettingEnabled() { 1102 boolean result = false; 1103 try { 1104 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1105 ImsManager imsMngr = mContext.getSystemService(ImsManager.class); 1106 ImsMmTelManager mmTelManager = imsMngr.getImsMmTelManager(getSubId()); 1107 if (isInRoaming()) { 1108 result = mmTelManager.isVoWiFiRoamingSettingEnabled(); 1109 } else { 1110 result = mmTelManager.isVoWiFiSettingEnabled(); 1111 } 1112 logi("isWifiCallingSettingEnabled " + result); 1113 return result; 1114 } 1115 } catch (Exception e) { 1116 logi("isWifiCallingSettingEnabled e=" + e); 1117 } 1118 return result; 1119 } 1120 getImsNetworkTypeConfiguration()1121 private @NonNull List<Integer> getImsNetworkTypeConfiguration() { 1122 int[] rats = mImsRatsConfig; 1123 if (isInRoaming()) rats = mImsRoamRatsConfig; 1124 1125 List<Integer> ratList = new ArrayList<Integer>(); 1126 for (int i = 0; i < rats.length; i++) { 1127 ratList.add(rats[i]); 1128 } 1129 return ratList; 1130 } 1131 getCsNetworkTypeConfiguration()1132 private @NonNull List<Integer> getCsNetworkTypeConfiguration() { 1133 int[] rats = mCsRatsConfig; 1134 if (isInRoaming()) rats = mCsRoamRatsConfig; 1135 1136 List<Integer> ratList = new ArrayList<Integer>(); 1137 for (int i = 0; i < rats.length; i++) { 1138 ratList.add(rats[i]); 1139 } 1140 1141 if (!mCdmaPreferredNumbers.isEmpty()) { 1142 if (mCdmaPreferredNumbers.contains(mSelectionAttributes.getNumber())) { 1143 // The number will be dialed over CDMA. 1144 ratList.clear(); 1145 ratList.add(new Integer(CDMA2000)); 1146 } else { 1147 // The number will be dialed over UTRAN or GERAN. 1148 ratList.remove(new Integer(CDMA2000)); 1149 } 1150 } 1151 1152 return ratList; 1153 } 1154 getDomainPreference()1155 private @NonNull List<Integer> getDomainPreference() { 1156 int[] domains = mDomainPreference; 1157 if (isInRoaming()) domains = mDomainPreferenceRoam; 1158 1159 List<Integer> domainList = new ArrayList<Integer>(); 1160 for (int i = 0; i < domains.length; i++) { 1161 domainList.add(domains[i]); 1162 } 1163 return domainList; 1164 } 1165 isInRoaming()1166 private boolean isInRoaming() { 1167 if (!SubscriptionManager.isValidSubscriptionId(getSubId())) return false; 1168 1169 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1170 tm = tm.createForSubscriptionId(getSubId()); 1171 String netIso = tm.getNetworkCountryIso(); 1172 1173 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 1174 if (regResult != null) { 1175 if (regResult.getRegState() == REGISTRATION_STATE_HOME) return false; 1176 if (regResult.getRegState() == REGISTRATION_STATE_ROAMING) return true; 1177 1178 String iso = regResult.getIso(); 1179 if (!TextUtils.isEmpty(iso)) netIso = iso; 1180 } 1181 1182 String simIso = tm.getSimCountryIso(); 1183 logi("isInRoaming simIso=" + simIso + ", netIso=" + netIso); 1184 1185 if (TextUtils.isEmpty(simIso)) return false; 1186 if (TextUtils.isEmpty(netIso)) return false; 1187 1188 return !(TextUtils.equals(simIso, netIso)); 1189 } 1190 1191 /** 1192 * Determines whether IMS is registered over Wi-Fi. 1193 * 1194 * @return {@code true} if IMS is registered over Wi-Fi. 1195 */ isImsRegisteredOverWifi()1196 private boolean isImsRegisteredOverWifi() { 1197 boolean ret = false; 1198 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1199 ret = mImsStateTracker.isImsRegisteredOverWlan(); 1200 } 1201 1202 logi("isImsRegisteredOverWifi " + ret); 1203 return ret; 1204 } 1205 1206 /** 1207 * Determines whether IMS is registered over the mobile data of another subscription. 1208 * 1209 * @return {@code true} if IMS is registered over the mobile data of another subscription. 1210 */ isImsRegisteredOverCrossSim()1211 private boolean isImsRegisteredOverCrossSim() { 1212 boolean ret = false; 1213 if (SubscriptionManager.isValidSubscriptionId(getSubId())) { 1214 ret = mImsStateTracker.isImsRegisteredOverCrossSim(); 1215 } 1216 1217 logi("isImsRegisteredOverCrossSim " + ret); 1218 return ret; 1219 } 1220 1221 /** 1222 * Determines whether IMS is registered with voice capability. 1223 * 1224 * @return {@code true} if IMS is registered with voice capability. 1225 */ isImsRegisteredWithVoiceCapability()1226 private boolean isImsRegisteredWithVoiceCapability() { 1227 boolean ret = mImsRegistered && mIsVoiceCapable; 1228 1229 logi("isImsRegisteredWithVoiceCapability " + ret); 1230 return ret; 1231 } 1232 onWlanSelected()1233 private void onWlanSelected() { 1234 logi("onWlanSelected"); 1235 if (mLastTransportType == TRANSPORT_TYPE_WLAN) { 1236 logi("onWlanSelected ignore duplicated callback"); 1237 return; 1238 } 1239 1240 mDomainSelected = true; 1241 mLastTransportType = TRANSPORT_TYPE_WLAN; 1242 mVoWifiTrialCount++; 1243 mTransportSelectorCallback.onWlanSelected(mVoWifiOverEmergencyPdn); 1244 mWwanSelectorCallback = null; 1245 removeMessages(MSG_NETWORK_SCAN_TIMEOUT); 1246 removeMessages(MSG_MAX_CELLULAR_TIMEOUT); 1247 } 1248 onWwanSelected(Runnable runnable)1249 private void onWwanSelected(Runnable runnable) { 1250 logi("onWwanSelected"); 1251 if (mLastTransportType == TRANSPORT_TYPE_WWAN) { 1252 logi("onWwanSelected ignore duplicated callback"); 1253 return; 1254 } 1255 1256 mLastTransportType = TRANSPORT_TYPE_WWAN; 1257 mTransportSelectorCallback.onWwanSelected((callback) -> { 1258 mWwanSelectorCallback = callback; 1259 runnable.run(); 1260 }); 1261 } 1262 onWwanNetworkTypeSelected(@adioAccessNetworkType int accessNetworkType)1263 private void onWwanNetworkTypeSelected(@RadioAccessNetworkType int accessNetworkType) { 1264 logi("onWwanNetworkTypeSelected " + accessNetworkTypeToString(accessNetworkType)); 1265 if (mWwanSelectorCallback == null) { 1266 logi("onWwanNetworkTypeSelected callback is null"); 1267 return; 1268 } 1269 1270 mDomainSelected = true; 1271 mLastNetworkType = accessNetworkType; 1272 int domain = NetworkRegistrationInfo.DOMAIN_CS; 1273 if (accessNetworkType == EUTRAN || accessNetworkType == NGRAN) { 1274 domain = NetworkRegistrationInfo.DOMAIN_PS; 1275 } 1276 mWwanSelectorCallback.onDomainSelected(domain, 1277 (domain == NetworkRegistrationInfo.DOMAIN_PS)); 1278 } 1279 1280 /** 1281 * Registers for changes to network connectivity. 1282 */ registerForConnectivityChanges()1283 private void registerForConnectivityChanges() { 1284 if (mIsMonitoringConnectivity) { 1285 return; 1286 } 1287 1288 ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1289 if (cm != null) { 1290 logi("registerForConnectivityChanges"); 1291 NetworkRequest.Builder builder = new NetworkRequest.Builder(); 1292 builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 1293 cm.registerNetworkCallback(builder.build(), mNetworkCallback); 1294 mIsMonitoringConnectivity = true; 1295 } 1296 } 1297 1298 /** 1299 * Unregisters for connectivity changes. 1300 */ unregisterForConnectivityChanges()1301 private void unregisterForConnectivityChanges() { 1302 if (!mIsMonitoringConnectivity) { 1303 return; 1304 } 1305 1306 ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); 1307 if (cm != null) { 1308 logi("unregisterForConnectivityChanges"); 1309 cm.unregisterNetworkCallback(mNetworkCallback); 1310 mIsMonitoringConnectivity = false; 1311 } 1312 } 1313 1314 /** Starts the max cellular timer. */ startMaxCellularTimer()1315 private void startMaxCellularTimer() { 1316 logd("startMaxCellularTimer tried=" + mVoWifiTrialCount 1317 + ", max=" + mMaxNumOfVoWifiTries); 1318 if (isEmcOverWifiSupported() 1319 && (mMaxCellularTimeout > 0) 1320 && (mVoWifiTrialCount < mMaxNumOfVoWifiTries)) { 1321 logi("startMaxCellularTimer start timer"); 1322 sendEmptyMessageDelayed(MSG_MAX_CELLULAR_TIMEOUT, mMaxCellularTimeout); 1323 registerForConnectivityChanges(); 1324 } 1325 } 1326 allowEmergencyCalls(EmergencyRegResult regResult)1327 private boolean allowEmergencyCalls(EmergencyRegResult regResult) { 1328 if (mModemCount < 2) return true; 1329 if (regResult == null) { 1330 loge("allowEmergencyCalls null regResult"); 1331 return true; 1332 } 1333 1334 String iso = regResult.getIso(); 1335 if (sAllowOnlyWithSimReady.contains(iso)) { 1336 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1337 int simState = tm.getSimState(getSlotId()); 1338 if (simState != TelephonyManager.SIM_STATE_READY) { 1339 logi("allowEmergencyCalls not ready, simState=" + simState + ", iso=" + iso); 1340 if (mCrossSimRedialingController.isThereOtherSlot()) { 1341 return false; 1342 } 1343 logi("allowEmergencyCalls there is no other slot available"); 1344 } 1345 } 1346 1347 return true; 1348 } 1349 terminateSelectionPermanentlyForSlot()1350 private void terminateSelectionPermanentlyForSlot() { 1351 logi("terminateSelectionPermanentlyForSlot"); 1352 terminateSelection(true); 1353 } 1354 terminateSelectionForCrossSimRedialing(boolean permanent)1355 private void terminateSelectionForCrossSimRedialing(boolean permanent) { 1356 logi("terminateSelectionForCrossSimRedialing perm=" + permanent); 1357 terminateSelection(permanent); 1358 } 1359 terminateSelection(boolean permanent)1360 private void terminateSelection(boolean permanent) { 1361 mTransportSelectorCallback.onSelectionTerminated(permanent 1362 ? DisconnectCause.EMERGENCY_PERM_FAILURE 1363 : DisconnectCause.EMERGENCY_TEMP_FAILURE); 1364 1365 if (mIsScanRequested && mCancelSignal != null) { 1366 mCancelSignal.cancel(); 1367 mCancelSignal = null; 1368 } 1369 } 1370 1371 /** Starts the cross stack timer. */ startCrossStackTimer()1372 public void startCrossStackTimer() { 1373 boolean inService = false; 1374 boolean inRoaming = false; 1375 1376 if (mModemCount == 1) return; 1377 1378 EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult(); 1379 if (regResult != null) { 1380 int regState = regResult.getRegState(); 1381 1382 if ((regResult.getDomain() > 0) 1383 && (regState == REGISTRATION_STATE_HOME 1384 || regState == REGISTRATION_STATE_ROAMING)) { 1385 inService = true; 1386 } 1387 inRoaming = (regState == REGISTRATION_STATE_ROAMING) || isInRoaming(); 1388 } 1389 1390 mCrossSimRedialingController.startTimer(mContext, this, mSelectionAttributes.getCallId(), 1391 mSelectionAttributes.getNumber(), inService, inRoaming, mModemCount); 1392 } 1393 1394 /** Notifies that the cross stack redilaing timer has been expired. */ notifyCrossStackTimerExpired()1395 public void notifyCrossStackTimerExpired() { 1396 logi("notifyCrossStackTimerExpired"); 1397 1398 mCrossStackTimerExpired = true; 1399 if (mDomainSelected) { 1400 // When reselecting domain, terminateSelection will be called. 1401 return; 1402 } 1403 terminateSelectionForCrossSimRedialing(false); 1404 } 1405 arrayToString(int[] intArray, IntFunction<String> func)1406 private static String arrayToString(int[] intArray, IntFunction<String> func) { 1407 int length = intArray.length; 1408 StringBuilder sb = new StringBuilder("{"); 1409 if (length > 0) { 1410 int i = 0; 1411 sb.append(func.apply(intArray[i++])); 1412 while (i < length) { 1413 sb.append(", ").append(func.apply(intArray[i++])); 1414 } 1415 } 1416 sb.append("}"); 1417 return sb.toString(); 1418 } 1419 arrayToString(String[] stringArray)1420 private static String arrayToString(String[] stringArray) { 1421 StringBuilder sb; 1422 int length = stringArray.length; 1423 sb = new StringBuilder("{"); 1424 if (length > 0) { 1425 int i = 0; 1426 sb.append(stringArray[i++]); 1427 while (i < length) { 1428 sb.append(", ").append(stringArray[i++]); 1429 } 1430 } 1431 sb.append("}"); 1432 return sb.toString(); 1433 } 1434 domainPreferenceToString( @arrierConfigManager.ImsEmergency.EmergencyDomain int domain)1435 private static String domainPreferenceToString( 1436 @CarrierConfigManager.ImsEmergency.EmergencyDomain int domain) { 1437 switch (domain) { 1438 case DOMAIN_CS: return "CS"; 1439 case DOMAIN_PS_3GPP: return "PS_3GPP"; 1440 case DOMAIN_PS_NON_3GPP: return "PS_NON_3GPP"; 1441 default: return "UNKNOWN"; 1442 } 1443 } 1444 carrierConfigNetworkScanTypeToString( @arrierConfigManager.ImsEmergency.EmergencyScanType int scanType)1445 private static String carrierConfigNetworkScanTypeToString( 1446 @CarrierConfigManager.ImsEmergency.EmergencyScanType int scanType) { 1447 switch (scanType) { 1448 case CarrierConfigManager.ImsEmergency.SCAN_TYPE_NO_PREFERENCE: return "NO_PREF"; 1449 case CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE: return "FULL"; 1450 case SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE: return "FULL_N_LIMITED"; 1451 default: return "UNKNOWN"; 1452 } 1453 } 1454 accessNetworkTypeToString( @adioAccessNetworkType int accessNetworkType)1455 private static String accessNetworkTypeToString( 1456 @RadioAccessNetworkType int accessNetworkType) { 1457 switch (accessNetworkType) { 1458 case AccessNetworkType.UNKNOWN: return "UNKNOWN"; 1459 case AccessNetworkType.GERAN: return "GERAN"; 1460 case AccessNetworkType.UTRAN: return "UTRAN"; 1461 case AccessNetworkType.EUTRAN: return "EUTRAN"; 1462 case AccessNetworkType.CDMA2000: return "CDMA2000"; 1463 case AccessNetworkType.IWLAN: return "IWLAN"; 1464 case AccessNetworkType.NGRAN: return "NGRAN"; 1465 default: return Integer.toString(accessNetworkType); 1466 } 1467 } 1468 1469 /** 1470 * Destroys the instance. 1471 */ 1472 @VisibleForTesting destroy()1473 public void destroy() { 1474 if (DBG) logd("destroy"); 1475 1476 mCrossSimRedialingController.stopTimer(); 1477 releaseWakeLock(); 1478 1479 mDestroyed = true; 1480 mImsStateTracker.removeBarringInfoListener(this); 1481 mImsStateTracker.removeImsStateListener(this); 1482 unregisterForConnectivityChanges(); 1483 1484 super.destroy(); 1485 } 1486 acquireWakeLock()1487 private void acquireWakeLock() { 1488 if (mPartialWakeLock != null) { 1489 synchronized (mPartialWakeLock) { 1490 logi("acquireWakeLock"); 1491 mPartialWakeLock.acquire(); 1492 } 1493 } 1494 } 1495 releaseWakeLock()1496 private void releaseWakeLock() { 1497 if (mPartialWakeLock != null) { 1498 synchronized (mPartialWakeLock) { 1499 if (mPartialWakeLock.isHeld()) { 1500 logi("releaseWakeLock"); 1501 mPartialWakeLock.release(); 1502 } 1503 } 1504 } 1505 } 1506 selectDomainForTestEmergencyNumber()1507 private void selectDomainForTestEmergencyNumber() { 1508 logi("selectDomainForTestEmergencyNumber"); 1509 if (isImsRegisteredWithVoiceCapability()) { 1510 onWwanNetworkTypeSelected(EUTRAN); 1511 } else { 1512 onWwanNetworkTypeSelected(UTRAN); 1513 } 1514 } 1515 isTestEmergencyNumber(String number)1516 private boolean isTestEmergencyNumber(String number) { 1517 number = PhoneNumberUtils.stripSeparators(number); 1518 Map<Integer, List<EmergencyNumber>> list = new HashMap<>(); 1519 try { 1520 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 1521 list = tm.getEmergencyNumberList(); 1522 } catch (IllegalStateException ise) { 1523 loge("isTestEmergencyNumber ise=" + ise); 1524 } 1525 1526 for (Integer sub : list.keySet()) { 1527 for (EmergencyNumber eNumber : list.get(sub)) { 1528 if (number.equals(eNumber.getNumber()) 1529 && eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST)) { 1530 logd("isTestEmergencyNumber: " + number + " is a test emergency number."); 1531 return true; 1532 } 1533 } 1534 } 1535 return false; 1536 } 1537 1538 @Override logi(String msg)1539 protected void logi(String msg) { 1540 super.logi(msg); 1541 sLocalLog.log(msg); 1542 } 1543 1544 @Override loge(String msg)1545 protected void loge(String msg) { 1546 super.loge(msg); 1547 sLocalLog.log(msg); 1548 } 1549 } 1550