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 android.annotation.NonNull; 20 import android.content.Context; 21 import android.os.Looper; 22 import android.os.PersistableBundle; 23 import android.telephony.AccessNetworkConstants; 24 import android.telephony.BarringInfo; 25 import android.telephony.CarrierConfigManager; 26 import android.telephony.DataSpecificRegistrationInfo; 27 import android.telephony.NetworkRegistrationInfo; 28 import android.telephony.ServiceState; 29 import android.telephony.TelephonyManager; 30 import android.telephony.VopsSupportInfo; 31 32 import com.android.internal.annotations.VisibleForTesting; 33 34 /** 35 * Implements an emergency SMS domain selector for sending an emergency SMS. 36 */ 37 public class EmergencySmsDomainSelector extends SmsDomainSelector implements 38 ImsStateTracker.BarringInfoListener, ImsStateTracker.ServiceStateListener { 39 /** 40 * Stores the configuration value of 41 * {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL}. 42 * This value is always updated whenever the domain selection is requested. 43 */ 44 private Boolean mEmergencySmsOverImsSupportedByConfig; 45 private ServiceState mServiceState; 46 private boolean mServiceStateReceived; 47 private BarringInfo mBarringInfo; 48 private boolean mBarringInfoReceived; 49 EmergencySmsDomainSelector(Context context, int slotId, int subId, @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker, @NonNull DestroyListener listener)50 public EmergencySmsDomainSelector(Context context, int slotId, int subId, 51 @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker, 52 @NonNull DestroyListener listener) { 53 super(context, slotId, subId, looper, imsStateTracker, listener, 54 "DomainSelector-EmergencySMS"); 55 56 mImsStateTracker.addServiceStateListener(this); 57 mImsStateTracker.addBarringInfoListener(this); 58 } 59 60 @Override destroy()61 public void destroy() { 62 if (mDestroyed) { 63 return; 64 } 65 mImsStateTracker.removeServiceStateListener(this); 66 mImsStateTracker.removeBarringInfoListener(this); 67 super.destroy(); 68 } 69 70 @Override finishSelection()71 public void finishSelection() { 72 super.finishSelection(); 73 mServiceStateReceived = false; 74 mServiceState = null; 75 mBarringInfoReceived = false; 76 mBarringInfo = null; 77 mEmergencySmsOverImsSupportedByConfig = null; 78 } 79 80 @Override onBarringInfoUpdated(BarringInfo barringInfo)81 public void onBarringInfoUpdated(BarringInfo barringInfo) { 82 mBarringInfoReceived = true; 83 mBarringInfo = barringInfo; 84 sendMessageForDomainSelection(); 85 } 86 87 @Override onServiceStateUpdated(ServiceState serviceState)88 public void onServiceStateUpdated(ServiceState serviceState) { 89 mServiceStateReceived = true; 90 mServiceState = serviceState; 91 sendMessageForDomainSelection(); 92 } 93 94 /** 95 * Checks whether the domain selector is ready to select the domain or not. 96 * The emergency SMS requires to be updated for the {@link ServiceState} and 97 * {@link BarringInfo} to confirm that the cellular network supports to send emergency SMS 98 * messages over IMS. 99 */ 100 @VisibleForTesting isDomainSelectionReady()101 public boolean isDomainSelectionReady() { 102 return mServiceStateReceived && mBarringInfoReceived; 103 } 104 105 @Override isSmsOverImsAvailable()106 protected boolean isSmsOverImsAvailable() { 107 if (super.isSmsOverImsAvailable()) { 108 /** 109 * Even though IMS is successfully registered, the cellular domain should be 110 * available for the emergency SMS according to the carrier's requirement 111 * when {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL} is set 112 * to true. 113 */ 114 if (isEmergencySmsOverImsSupportedIfLteLimitedOrInService()) { 115 /** 116 * Emergency SMS should be supported via emergency PDN. 117 * If this condition is false, then need to fallback to CS network 118 * because the current PS network does not allow the emergency service. 119 */ 120 return isNetworkAvailableForImsEmergencySms(); 121 } 122 123 // Emergency SMS is supported via IMS PDN. 124 return true; 125 } 126 127 return isImsEmergencySmsAvailable(); 128 } 129 130 @Override selectDomain()131 protected void selectDomain() { 132 if (!isDomainSelectionRequested()) { 133 logi("Domain selection is not requested!"); 134 return; 135 } 136 137 if (!isDomainSelectionReady()) { 138 logd("Wait for the readiness of the domain selection!"); 139 return; 140 } 141 142 logi("selectDomain: " + mImsStateTracker.imsStateToString()); 143 144 if (isSmsOverImsAvailable()) { 145 boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService = 146 isEmergencySmsOverImsSupportedIfLteLimitedOrInService(); 147 148 if (mImsStateTracker.isImsRegisteredOverWlan()) { 149 /** 150 * When {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL} 151 * is set to true, the emergency SMS supports on the LTE network using the 152 * emergency PDN. As of now, since the emergency SMS doesn't use the emergency PDN 153 * over WLAN, the domain selector reports the domain as WLAN only if 154 * {@code isEmergencySmsOverImsSupportedIfLteLimitedOrInService} is set to false 155 * and IMS is registered over WLAN. 156 * Otherwise, the domain selector reports the domain as WWAN. 157 */ 158 if (!isEmergencySmsOverImsSupportedIfLteLimitedOrInService) { 159 notifyWlanSelected(false); 160 return; 161 } 162 163 logi("DomainSelected: WLAN >> WWAN"); 164 } 165 notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_PS, 166 isEmergencySmsOverImsSupportedIfLteLimitedOrInService); 167 } else { 168 notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_CS, false); 169 } 170 } 171 172 /** 173 * Checks if the emergency SMS messages over IMS is available according to the carrier 174 * configuration and the current network states. 175 */ isImsEmergencySmsAvailable()176 private boolean isImsEmergencySmsAvailable() { 177 boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService = 178 isEmergencySmsOverImsSupportedIfLteLimitedOrInService(); 179 boolean networkAvailable = isNetworkAvailableForImsEmergencySms(); 180 181 logi("isImsEmergencySmsAvailable: " 182 + "emergencySmsOverIms=" + isEmergencySmsOverImsSupportedIfLteLimitedOrInService 183 + ", mmTelFeatureAvailable=" + mImsStateTracker.isMmTelFeatureAvailable() 184 + ", networkAvailable=" + networkAvailable); 185 186 return isEmergencySmsOverImsSupportedIfLteLimitedOrInService 187 && mImsStateTracker.isMmTelFeatureAvailable() 188 && networkAvailable; 189 } 190 191 /** 192 * Checks if sending emergency SMS messages over IMS is supported when in LTE/limited LTE 193 * (Emergency only) service mode from the carrier configuration. 194 */ isEmergencySmsOverImsSupportedIfLteLimitedOrInService()195 private boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService() { 196 if (mEmergencySmsOverImsSupportedByConfig == null) { 197 CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class); 198 199 if (ccm == null) { 200 loge("CarrierConfigManager is null"); 201 return false; 202 } 203 204 PersistableBundle b = ccm.getConfigForSubId(getSubId()); 205 206 if (b == null) { 207 loge("PersistableBundle is null"); 208 return false; 209 } 210 211 mEmergencySmsOverImsSupportedByConfig = b.getBoolean( 212 CarrierConfigManager.KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL); 213 } 214 215 return mEmergencySmsOverImsSupportedByConfig; 216 } 217 218 /** 219 * Checks if the emergency service is available in the LTE service mode. 220 */ isLteEmergencyAvailableInService()221 private boolean isLteEmergencyAvailableInService() { 222 if (mServiceState == null) { 223 return false; 224 } 225 226 final NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo( 227 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 228 229 if (regInfo != null 230 && regInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_LTE 231 && regInfo.isRegistered()) { 232 return isEmergencyServiceSupported(regInfo) && isEmergencyServiceAllowed(); 233 } 234 return false; 235 } 236 237 /** 238 * Checks if the emergency service is available in the limited LTE service(Emergency only) mode. 239 */ isLteEmergencyAvailableInLimitedService()240 private boolean isLteEmergencyAvailableInLimitedService() { 241 if (mServiceState == null) { 242 return false; 243 } 244 245 final NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo( 246 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 247 if (regInfo != null 248 && regInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_LTE 249 && regInfo.isEmergencyEnabled()) { 250 return isEmergencyServiceSupported(regInfo) && isEmergencyServiceAllowed(); 251 } 252 return false; 253 } 254 255 /** 256 * Checks if the network is available for the IMS emergency SMS. 257 */ isNetworkAvailableForImsEmergencySms()258 private boolean isNetworkAvailableForImsEmergencySms() { 259 return isLteEmergencyAvailableInService() 260 || isLteEmergencyAvailableInLimitedService(); 261 } 262 263 /** 264 * Checks if the emergency service is supported by the network. 265 * 266 * This checks if "Emergency bearer services indicator (EMC-BS)" field (bits) set to 267 * the "Emergency bearer services in S1 mode supported". 268 * 269 * @return {@code true} if the emergency service is supported by the network, 270 * {@code false} otherwise. 271 */ isEmergencyServiceSupported(@onNull NetworkRegistrationInfo regInfo)272 private boolean isEmergencyServiceSupported(@NonNull NetworkRegistrationInfo regInfo) { 273 final DataSpecificRegistrationInfo dsRegInfo = regInfo.getDataSpecificInfo(); 274 if (dsRegInfo != null) { 275 final VopsSupportInfo vopsSupportInfo = dsRegInfo.getVopsSupportInfo(); 276 return vopsSupportInfo != null 277 && vopsSupportInfo.isEmergencyServiceSupported(); 278 } 279 return false; 280 } 281 282 /** 283 * Checks if the emergency service is allowed (not barred) by the network. 284 * 285 * This checks if SystemInformationBlockType2 includes the ac-BarringInfo and 286 * with the ac-BarringForEmergency set to FALSE or 287 * if the SystemInformationBlockType2 does not include the ac-BarringInfo. 288 * 289 * @return {@code true} if the emergency service is allowed by the network, 290 * {@code false} otherwise. 291 */ isEmergencyServiceAllowed()292 private boolean isEmergencyServiceAllowed() { 293 if (mBarringInfo == null) { 294 return true; 295 } 296 final BarringInfo.BarringServiceInfo bsi = 297 mBarringInfo.getBarringServiceInfo(BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY); 298 return !bsi.isBarred(); 299 } 300 } 301