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 android.telephony.mockmodem; 18 19 import android.annotation.NonNull; 20 import android.hardware.radio.RadioError; 21 import android.hardware.radio.RadioIndicationType; 22 import android.hardware.radio.RadioResponseInfo; 23 import android.hardware.radio.ims.ConnectionFailureInfo; 24 import android.hardware.radio.ims.IRadioIms; 25 import android.hardware.radio.ims.IRadioImsIndication; 26 import android.hardware.radio.ims.IRadioImsResponse; 27 import android.hardware.radio.ims.ImsDeregistrationReason; 28 import android.os.RemoteException; 29 import android.telephony.ims.feature.MmTelFeature; 30 import android.telephony.ims.stub.ImsRegistrationImplBase; 31 import android.util.Log; 32 33 import java.util.List; 34 35 public class IRadioImsImpl extends IRadioIms.Stub { 36 private static final String TAG = "MRIMS"; 37 38 private final MockModemService mService; 39 private IRadioImsResponse mRadioImsResponse; 40 private IRadioImsIndication mRadioImsIndication; 41 private final MockModemConfigInterface mMockModemConfigInterface; 42 private final int mSubId; 43 private final String mTag; 44 45 private final MockImsService mImsState = new MockImsService(); 46 47 private boolean mBlockStartImsTrafficResponse = false; 48 IRadioImsImpl( MockModemService service, MockModemConfigInterface configInterface, int instanceId)49 public IRadioImsImpl( 50 MockModemService service, MockModemConfigInterface configInterface, int instanceId) { 51 mTag = TAG + "-" + instanceId; 52 Log.d(mTag, "Instantiated"); 53 54 this.mService = service; 55 mMockModemConfigInterface = configInterface; 56 mSubId = instanceId; 57 } 58 59 // Implementation of IRadioIms functions 60 @Override setResponseFunctions( IRadioImsResponse radioImsResponse, IRadioImsIndication radioImsIndication)61 public void setResponseFunctions( 62 IRadioImsResponse radioImsResponse, IRadioImsIndication radioImsIndication) { 63 Log.d(mTag, "setResponseFunctions"); 64 mRadioImsResponse = radioImsResponse; 65 mRadioImsIndication = radioImsIndication; 66 mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY); 67 } 68 69 @Override setSrvccCallInfo(int serial, android.hardware.radio.ims.SrvccCall[] srvccCalls)70 public void setSrvccCallInfo(int serial, android.hardware.radio.ims.SrvccCall[] srvccCalls) { 71 Log.d(mTag, "setSrvccCallInfo"); 72 73 mImsState.setSrvccCallInfo(srvccCalls); 74 75 RadioResponseInfo rsp = mService.makeSolRsp(serial); 76 try { 77 mRadioImsResponse.setSrvccCallInfoResponse(rsp); 78 } catch (RemoteException ex) { 79 Log.e(mTag, "Failed to setSrvccCallInfo from AIDL. Exception" + ex); 80 } 81 } 82 83 @Override updateImsRegistrationInfo(int serial, android.hardware.radio.ims.ImsRegistration imsRegistration)84 public void updateImsRegistrationInfo(int serial, 85 android.hardware.radio.ims.ImsRegistration imsRegistration) { 86 Log.d(mTag, "updateImsRegistrationInfo"); 87 88 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 89 try { 90 mRadioImsResponse.updateImsRegistrationInfoResponse(rsp); 91 } catch (RemoteException ex) { 92 Log.e(mTag, "Failed to updateImsRegistrationInfo from AIDL. Exception" + ex); 93 } 94 } 95 96 @Override startImsTraffic(int serial, int token, int imsTrafficType, int accessNetworkType, int trafficDirection)97 public void startImsTraffic(int serial, 98 int token, int imsTrafficType, int accessNetworkType, int trafficDirection) { 99 Log.d(mTag, "startImsTraffic"); 100 101 mImsState.startImsTraffic(serial, token, imsTrafficType); 102 103 if (mBlockStartImsTrafficResponse) return; 104 105 ConnectionFailureInfo failureInfo = null; 106 RadioResponseInfo rsp = mService.makeSolRsp(serial); 107 try { 108 mRadioImsResponse.startImsTrafficResponse(rsp, failureInfo); 109 } catch (RemoteException ex) { 110 Log.e(mTag, "Failed to startImsTraffic from AIDL. Exception" + ex); 111 } 112 } 113 114 @Override stopImsTraffic(int serial, int token)115 public void stopImsTraffic(int serial, int token) { 116 Log.d(mTag, "stopImsTraffic"); 117 118 mImsState.stopImsTraffic(token); 119 120 RadioResponseInfo rsp = mService.makeSolRsp(serial); 121 try { 122 mRadioImsResponse.stopImsTrafficResponse(rsp); 123 } catch (RemoteException ex) { 124 Log.e(mTag, "Failed to stopImsTraffic from AIDL. Exception" + ex); 125 } 126 } 127 128 @Override triggerEpsFallback(int serial, int reason)129 public void triggerEpsFallback(int serial, int reason) { 130 Log.d(mTag, "triggerEpsFallback"); 131 132 mImsState.setEpsFallbackReason(reason); 133 134 RadioResponseInfo rsp = mService.makeSolRsp(serial); 135 try { 136 mRadioImsResponse.triggerEpsFallbackResponse(rsp); 137 } catch (RemoteException ex) { 138 Log.e(mTag, "Failed to triggerEpsFallback from AIDL. Exception" + ex); 139 } 140 } 141 142 @Override sendAnbrQuery(int serial, int qosSessionId, int direction, int bitsPerSecond)143 public void sendAnbrQuery(int serial, int qosSessionId, int direction, int bitsPerSecond) { 144 Log.d(mTag, "sendAnbrQuery"); 145 146 mImsState.sendAnbrQuery(qosSessionId, direction, bitsPerSecond); 147 148 RadioResponseInfo rsp = mService.makeSolRsp(serial); 149 try { 150 mRadioImsResponse.sendAnbrQueryResponse(rsp); 151 } catch (RemoteException ex) { 152 Log.e(mTag, "Failed to sendAnbrQuery from AIDL. Exception" + ex); 153 } 154 } 155 onConnectionSetupFailure(int token, @NonNull ConnectionFailureInfo failureInfo)156 public void onConnectionSetupFailure(int token, @NonNull ConnectionFailureInfo failureInfo) { 157 Log.d(mTag, "onConnectionSetupFailure"); 158 159 if (mRadioImsIndication != null) { 160 try { 161 mRadioImsIndication.onConnectionSetupFailure( 162 RadioIndicationType.UNSOLICITED, token, failureInfo); 163 } catch (RemoteException ex) { 164 Log.e(mTag, "Failed to onConnectionSetupFailure indication from AIDL. Exception" 165 + ex); 166 } 167 } else { 168 Log.e(mTag, "null mRadioImsIndication"); 169 } 170 } 171 notifyAnbr(int qosSessionId, int direction, int bitsPerSecond)172 public void notifyAnbr(int qosSessionId, int direction, int bitsPerSecond) { 173 Log.d(mTag, "notifyAnbr"); 174 175 if (mRadioImsIndication != null) { 176 try { 177 mRadioImsIndication.notifyAnbr(RadioIndicationType.UNSOLICITED, 178 qosSessionId, direction, bitsPerSecond); 179 } catch (RemoteException ex) { 180 Log.e(mTag, "Failed to notifyAnbr indication from AIDL. Exception" + ex); 181 } 182 } else { 183 Log.e(mTag, "null mRadioImsIndication"); 184 } 185 } 186 triggerImsDeregistration( @msRegistrationImplBase.ImsDeregistrationReason int reason)187 public void triggerImsDeregistration( 188 @ImsRegistrationImplBase.ImsDeregistrationReason int reason) { 189 Log.d(mTag, "triggerImsDeregistration"); 190 191 int halReason; 192 switch (reason) { 193 case ImsRegistrationImplBase.REASON_SIM_REFRESH: 194 halReason = ImsDeregistrationReason.REASON_SIM_REFRESH; 195 break; 196 case ImsRegistrationImplBase.REASON_ALLOWED_NETWORK_TYPES_CHANGED: 197 halReason = ImsDeregistrationReason.REASON_ALLOWED_NETWORK_TYPES_CHANGED; 198 break; 199 default: 200 halReason = ImsDeregistrationReason.REASON_SIM_REMOVED; 201 break; 202 } 203 204 if (mRadioImsIndication != null) { 205 try { 206 mRadioImsIndication.triggerImsDeregistration( 207 RadioIndicationType.UNSOLICITED, halReason); 208 } catch (RemoteException ex) { 209 Log.e(mTag, "Failed to triggerImsDeregistration indication from AIDL. Exception" 210 + ex); 211 } 212 } else { 213 Log.e(mTag, "null mRadioImsIndication"); 214 } 215 } 216 217 /** @return The list of {@link MockSrvccCall} instances. */ getSrvccCalls()218 public List<MockSrvccCall> getSrvccCalls() { 219 return mImsState.getSrvccCalls(); 220 } 221 222 /** 223 * Stop sending default response to startImsTraffic. 224 * 225 * @param blocked indicates whether sending response is allowed or not. 226 */ blockStartImsTrafficResponse(boolean blocked)227 public void blockStartImsTrafficResponse(boolean blocked) { 228 mBlockStartImsTrafficResponse = blocked; 229 } 230 231 /** 232 * Returns whether the given IMS traffic type is started or not. 233 * 234 * @param trafficType the IMS traffic type 235 * @return boolean true if the given IMS traffic type is started 236 */ isImsTrafficStarted( @ndroid.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType)237 public boolean isImsTrafficStarted( 238 @android.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType) { 239 return mImsState.isImsTrafficStarted(trafficType); 240 } 241 242 /** 243 * Clears the IMS traffic state. 244 */ clearImsTrafficState()245 public void clearImsTrafficState() { 246 mBlockStartImsTrafficResponse = false; 247 mImsState.clearImsTrafficState(); 248 } 249 250 /** 251 * Sends the response with the given information. 252 * 253 * @param trafficType the IMS traffic type 254 * @param reason The reason of failure. 255 * @param causeCode Failure cause code from network or modem specific to the failure. 256 * @param waitTimeMillis Retry wait time provided by network in milliseconds. 257 */ sendStartImsTrafficResponse( @ndroid.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType, @android.telephony.ims.feature.ConnectionFailureInfo.FailureReason int reason, int causeCode, int waitTimeMillis)258 public void sendStartImsTrafficResponse( 259 @android.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType, 260 @android.telephony.ims.feature.ConnectionFailureInfo.FailureReason int reason, 261 int causeCode, int waitTimeMillis) { 262 263 ConnectionFailureInfo failureInfo = null; 264 if (reason != 0) { 265 failureInfo = new ConnectionFailureInfo(); 266 failureInfo.failureReason = reason; 267 failureInfo.causeCode = causeCode; 268 failureInfo.waitTimeMillis = waitTimeMillis; 269 } 270 271 RadioResponseInfo rsp = mService.makeSolRsp(mImsState.getImsTrafficSerial(trafficType)); 272 try { 273 mRadioImsResponse.startImsTrafficResponse(rsp, failureInfo); 274 } catch (RemoteException ex) { 275 Log.e(TAG, "Failed to startImsTrafficResponse from AIDL. Exception" + ex); 276 } 277 } 278 279 /** 280 * Notifies the connection failure info 281 * 282 * @param trafficType the IMS traffic type 283 * @param reason The reason of failure. 284 * @param causeCode Failure cause code from network or modem specific to the failure. 285 * @param waitTimeMillis Retry wait time provided by network in milliseconds. 286 */ sendConnectionFailureInfo( @ndroid.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType, @android.telephony.ims.feature.ConnectionFailureInfo.FailureReason int reason, int causeCode, int waitTimeMillis)287 public void sendConnectionFailureInfo( 288 @android.telephony.ims.feature.MmTelFeature.ImsTrafficType int trafficType, 289 @android.telephony.ims.feature.ConnectionFailureInfo.FailureReason int reason, 290 int causeCode, int waitTimeMillis) { 291 292 ConnectionFailureInfo failureInfo = new ConnectionFailureInfo(); 293 failureInfo.failureReason = reason; 294 failureInfo.causeCode = causeCode; 295 failureInfo.waitTimeMillis = waitTimeMillis; 296 297 onConnectionSetupFailure(mImsState.getImsTrafficToken(trafficType), failureInfo); 298 } 299 300 @Override updateImsCallStatus(int serial, android.hardware.radio.ims.ImsCall[] imsCalls)301 public void updateImsCallStatus(int serial, android.hardware.radio.ims.ImsCall[] imsCalls) { 302 Log.d(mTag, "updateImsCallStatus"); 303 304 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 305 try { 306 mRadioImsResponse.updateImsCallStatusResponse(rsp); 307 } catch (RemoteException ex) { 308 Log.e(mTag, "Failed to updateImsCallStatus from AIDL. Exception" + ex); 309 } 310 } 311 312 /** 313 * Returns the reason that caused EPS fallback. 314 * 315 * @return the reason that caused EPS fallback. 316 */ getEpsFallbackReason()317 public @MmTelFeature.EpsFallbackReason int getEpsFallbackReason() { 318 return mImsState.getEpsFallbackReason(); 319 } 320 321 /** 322 * Clears the EPS fallback reason. 323 */ resetEpsFallbackReason()324 public void resetEpsFallbackReason() { 325 mImsState.resetEpsFallbackReason(); 326 } 327 328 /** 329 * Returns the Anbr values triggered by Anbr Query. 330 * 331 * @return the Anbr values triggered by Anbr Query. 332 */ getAnbrValues()333 public int[] getAnbrValues() { 334 return mImsState.getAnbrValues(); 335 } 336 337 /** 338 * Clears the Anbr values. 339 */ resetAnbrValues()340 public void resetAnbrValues() { 341 mImsState.resetAnbrValues(); 342 } 343 344 /** 345 * Waits for the event of IMS state. 346 * 347 * @param latchIndex The index of the event. 348 * @param waitMs The timeout in milliseconds. 349 */ waitForLatchCountdown(int latchIndex, int waitMs)350 public boolean waitForLatchCountdown(int latchIndex, int waitMs) { 351 return mImsState.waitForLatchCountdown(latchIndex, waitMs); 352 } 353 354 /** 355 * Resets the CountDownLatches 356 */ resetAllLatchCountdown()357 public void resetAllLatchCountdown() { 358 mImsState.resetAllLatchCountdown(); 359 } 360 361 @Override getInterfaceHash()362 public String getInterfaceHash() { 363 return IRadioIms.HASH; 364 } 365 366 @Override getInterfaceVersion()367 public int getInterfaceVersion() { 368 return IRadioIms.VERSION; 369 } 370 } 371