Add RadioImaProxy, ImsResponse, and ImsIndication for IRadioIms
Bug: 216387835
Test: build & flash
Change-Id: I278089c761cc9c5066db084d0169c1607ebe1b62
Merged-In: I278089c761cc9c5066db084d0169c1607ebe1b62
diff --git a/Android.bp b/Android.bp
index d784fc8..eb16ba5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,6 +85,7 @@
"android.hardware.radio-V1.6-java",
"android.hardware.radio.config-V1-java",
"android.hardware.radio.data-V1-java",
+ "android.hardware.radio.ims-V1-java",
"android.hardware.radio.messaging-V1-java",
"android.hardware.radio.modem-V1-java",
"android.hardware.radio.network-V2-java",
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index 764458a..25cd6c7 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -115,6 +115,8 @@
protected RegistrantList mSimPhonebookChangedRegistrants = new RegistrantList();
protected RegistrantList mSimPhonebookRecordsReceivedRegistrants = new RegistrantList();
protected RegistrantList mEmergencyNetworkScanRegistrants = new RegistrantList();
+ protected RegistrantList mConnectionSetupFailureRegistrants = new RegistrantList();
+ protected RegistrantList mAccessAllowedRegistrants = new RegistrantList();
@UnsupportedAppUsage
protected Registrant mGsmSmsRegistrant;
@@ -1155,4 +1157,24 @@
public void unregisterForEmergencyNetworkScan(Handler h) {
mEmergencyNetworkScanRegistrants.remove(h);
}
+
+ @Override
+ public void registerForConnectionSetupFailure(Handler h, int what, Object obj) {
+ mConnectionSetupFailureRegistrants.addUnique(h, what, obj);
+ }
+
+ @Override
+ public void unregisterForConnectionSetupFailure(Handler h) {
+ mConnectionSetupFailureRegistrants.remove(h);
+ }
+
+ @Override
+ public void registerForAccessAllowed(Handler h, int what, Object obj) {
+ mAccessAllowedRegistrants.addUnique(h, what, obj);
+ }
+
+ @Override
+ public void unregisterForAccessAllowed(Handler h) {
+ mAccessAllowedRegistrants.remove(h);
+ }
}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index cdde40e..329abee 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2747,6 +2747,38 @@
public void unregisterForSimPhonebookRecordsReceived(Handler h);
/**
+ * Registers for notifications when connection setup fails.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ default void registerForConnectionSetupFailure(Handler h, int what, Object obj) {}
+
+ /**
+ * Unregisters for notifications when connection setup fails.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ default void unregisterForConnectionSetupFailure(Handler h) {}
+
+ /**
+ * Register for notifications when IMS traffic access is allowed
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ default void registerForAccessAllowed(Handler h, int what, Object obj) {}
+
+ /**
+ * Unregister for notifications when IMS traffic access is allowed
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ default void unregisterForAccessAllowed(Handler h) {}
+
+ /**
* Set the UE's usage setting.
*
* @param result Callback message containing the success or failure status.
@@ -2777,4 +2809,39 @@
* @param h Handler to be removed from the registrant list.
*/
default void unregisterForEmergencyNetworkScan(Handler h) {}
+
+ /**
+ * Provides a list of SRVCC call information to radio
+ *
+ * @param srvccConnections the list of connections.
+ */
+ default void setSrvccCallInfo(SrvccConnection[] srvccConnections, Message result) {}
+
+ /**
+ * Updates the IMS registration information to the radio.
+ *
+ * @param state the current IMS registration state.
+ * @param ipcan the type of IP connectivity access network where IMS features are registered.
+ * @param reason a failure reason for IMS registration.
+ * @param features IMS features such as VOICE, VIDEO and SMS.
+ */
+ default void updateImsRegistrationInfo(int state,
+ int ipcan, int reason, int features, Message result) {}
+
+ /**
+ * Notifies the NAS and RRC layers of the radio the type of upcoming IMS traffic.
+ *
+ * @param token The token of the request.
+ * @param trafficType IMS traffic type like registration, voice, video, SMS, emergency, and etc.
+ * @param isStart true when the traffic flow starts, false when traffic flow stops.
+ */
+ default void notifyImsTraffic(int token, int trafficType, boolean isStart, Message result) {}
+
+ /**
+ * Checks access class barring checks based on ImsTrafficType.
+ *
+ * @param token The token of the request.
+ * @param trafficType IMS traffic type like registration, voice, video, SMS, emergency, and etc.
+ */
+ default void performAcbCheck(int token, int trafficType, Message result) {}
}
diff --git a/src/java/com/android/internal/telephony/ImsIndication.java b/src/java/com/android/internal/telephony/ImsIndication.java
new file mode 100644
index 0000000..5436607
--- /dev/null
+++ b/src/java/com/android/internal/telephony/ImsIndication.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ACCESS_ALLOWED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CONNECTION_SETUP_FAILURE;
+
+import android.hardware.radio.ims.IRadioImsIndication;
+import android.os.AsyncResult;
+
+/**
+ * Interface declaring unsolicited radio indications for IMS APIs.
+ */
+public class ImsIndication extends IRadioImsIndication.Stub {
+ private final RIL mRil;
+
+ public ImsIndication(RIL ril) {
+ mRil = ril;
+ }
+
+ /**
+ * Fired by radio when any IMS traffic is not sent to network due to any failure
+ * on cellular networks.
+ *
+ * @param indicationType Type of radio indication.
+ * @param token The token provided by {@link #notifyImsTraffic} or {@link #performACBcheck}.
+ * @param info Connection failure information.
+ */
+ public void onConnectionSetupFailure(int indicationType, int token,
+ android.hardware.radio.ims.ConnectionFailureInfo info) {
+ mRil.processIndication(RIL.IMS_SERVICE, indicationType);
+
+ int[] response = new int[4];
+ response[0] = token;
+ response[1] = info.failureReason;
+ response[2] = info.causeCode;
+ response[3] = info.waitTimeMillis;
+
+ if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_CONNECTION_SETUP_FAILURE, response);
+
+ mRil.mConnectionSetupFailureRegistrants.notifyRegistrants(
+ new AsyncResult(null, response, null));
+ }
+
+ /**
+ * Fired by radio in response to {@link #performAcbCheck}
+ * if the access class check is allowed for the requested traffic type.
+ *
+ * @param indicationType Type of radio indication
+ * @param token The token provided by {@link #performAcbCheck}
+ */
+ public void onAccessAllowed(int indicationType, int token) {
+ mRil.processIndication(RIL.IMS_SERVICE, indicationType);
+
+ int[] response = new int[1];
+ response[0] = token;
+
+ if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_ACCESS_ALLOWED, response);
+
+ mRil.mAccessAllowedRegistrants.notifyRegistrants(new AsyncResult(null, response, null));
+ }
+}
diff --git a/src/java/com/android/internal/telephony/ImsResponse.java b/src/java/com/android/internal/telephony/ImsResponse.java
new file mode 100644
index 0000000..4664c1e
--- /dev/null
+++ b/src/java/com/android/internal/telephony/ImsResponse.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.ims.IRadioImsResponse;
+
+/**
+ * Interface declaring response functions to solicited radio requests for IMS APIs.
+ */
+public class ImsResponse extends IRadioImsResponse.Stub {
+ private final RIL mRil;
+
+ public ImsResponse(RIL ril) {
+ mRil = ril;
+ }
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ */
+ public void setSrvccCallInfoResponse(RadioResponseInfo info) {
+ RadioResponse.responseVoid(RIL.IMS_SERVICE, mRil, info);
+ }
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ */
+ public void updateImsRegistrationInfoResponse(RadioResponseInfo info) {
+ RadioResponse.responseVoid(RIL.IMS_SERVICE, mRil, info);
+ }
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ */
+ public void notifyImsTrafficResponse(RadioResponseInfo info) {
+ RadioResponse.responseVoid(RIL.IMS_SERVICE, mRil, info);
+ }
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error.
+ */
+ public void performAcbCheckResponse(RadioResponseInfo info) {
+ RadioResponse.responseVoid(RIL.IMS_SERVICE, mRil, info);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index c9cfc4d..11ba496 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -208,8 +208,9 @@
static final int NETWORK_SERVICE = 4;
static final int SIM_SERVICE = 5;
static final int VOICE_SERVICE = 6;
+ static final int IMS_SERVICE = 7;
static final int MIN_SERVICE_IDX = RADIO_SERVICE;
- static final int MAX_SERVICE_IDX = VOICE_SERVICE;
+ static final int MAX_SERVICE_IDX = IMS_SERVICE;
/**
* An array of sets that records if services are disabled in the HAL for a specific phone ID
@@ -236,6 +237,8 @@
private volatile IRadio mRadioProxy = null;
private DataResponse mDataResponse;
private DataIndication mDataIndication;
+ private ImsResponse mImsResponse;
+ private ImsIndication mImsIndication;
private MessagingResponse mMessagingResponse;
private MessagingIndication mMessagingIndication;
private ModemResponse mModemResponse;
@@ -707,8 +710,8 @@
/**
* Returns a {@link RadioDataProxy}, {@link RadioMessagingProxy}, {@link RadioModemProxy},
- * {@link RadioNetworkProxy}, {@link RadioSimProxy}, {@link RadioVoiceProxy}, or an empty {@link RadioServiceProxy}
- * if the service is not available.
+ * {@link RadioNetworkProxy}, {@link RadioSimProxy}, {@link RadioVoiceProxy},
+ * {@link RadioImsProxy}, or null if the service is not available.
*/
@NonNull
public <T extends RadioServiceProxy> T getRadioServiceProxy(Class<T> serviceClass,
@@ -731,6 +734,9 @@
if (serviceClass == RadioVoiceProxy.class) {
return (T) getRadioServiceProxy(VOICE_SERVICE, result);
}
+ if (serviceClass == RadioImsProxy.class) {
+ return (T) getRadioServiceProxy(IMS_SERVICE, result);
+ }
riljLoge("getRadioServiceProxy: unrecognized " + serviceClass);
return null;
}
@@ -851,6 +857,21 @@
.asInterface(binder));
}
break;
+ case IMS_SERVICE:
+ if (mMockModem == null) {
+ binder = ServiceManager.waitForDeclaredService(
+ android.hardware.radio.ims.IRadioIms.DESCRIPTOR + "/"
+ + HIDL_SERVICE_NAME[mPhoneId]);
+ } else {
+ binder = mMockModem.getServiceBinder(IMS_SERVICE);
+ }
+ if (binder != null) {
+ mRadioVersion = RADIO_HAL_VERSION_2_1;
+ ((RadioImsProxy) serviceProxy).setAidl(mRadioVersion,
+ android.hardware.radio.ims.IRadioIms.Stub
+ .asInterface(binder));
+ }
+ break;
}
if (serviceProxy.isEmpty() && mRadioVersion.less(RADIO_HAL_VERSION_2_0)) {
@@ -962,6 +983,12 @@
((RadioVoiceProxy) serviceProxy).getAidl().setResponseFunctions(
mVoiceResponse, mVoiceIndication);
break;
+ case IMS_SERVICE:
+ mDeathRecipients.get(service).linkToDeath(
+ ((RadioImsProxy) serviceProxy).getAidl().asBinder());
+ ((RadioImsProxy) serviceProxy).getAidl().setResponseFunctions(
+ mImsResponse, mImsIndication);
+ break;
}
} else {
if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_0)) {
@@ -1062,6 +1089,8 @@
mRadioIndication = new RadioIndication(this);
mDataResponse = new DataResponse(this);
mDataIndication = new DataIndication(this);
+ mImsResponse = new ImsResponse(this);
+ mImsIndication = new ImsIndication(this);
mMessagingResponse = new MessagingResponse(this);
mMessagingIndication = new MessagingIndication(this);
mModemResponse = new ModemResponse(this);
@@ -1088,6 +1117,7 @@
mServiceProxies.put(NETWORK_SERVICE, new RadioNetworkProxy());
mServiceProxies.put(SIM_SERVICE, new RadioSimProxy());
mServiceProxies.put(VOICE_SERVICE, new RadioVoiceProxy());
+ mServiceProxies.put(IMS_SERVICE, new RadioImsProxy());
} else {
mServiceProxies = proxies;
}
@@ -5089,6 +5119,133 @@
}
}
+ @Override
+ public void setSrvccCallInfo(SrvccConnection[] srvccConnections, Message result) {
+ RadioImsProxy imsProxy = getRadioServiceProxy(RadioImsProxy.class, result);
+ if (imsProxy.isEmpty()) return;
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_1)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_SET_SRVCC_CALL_INFO, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ // Do not log function arg for privacy
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ }
+
+ try {
+ imsProxy.setSrvccCallInfo(rr.mSerial,
+ RILUtils.convertToHalSrvccCall(srvccConnections));
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(IMS_SERVICE, "setSrvccCallInfo", e);
+ }
+ } else {
+ if (RILJ_LOGD) {
+ Rlog.d(RILJ_LOG_TAG, "setSrvccCallInfo: REQUEST_NOT_SUPPORTED");
+ }
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ public void updateImsRegistrationInfo(int state,
+ int ipcan, int reason, int features, Message result) {
+ RadioImsProxy imsProxy = getRadioServiceProxy(RadioImsProxy.class, result);
+ if (imsProxy.isEmpty()) return;
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_1)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_UPDATE_IMS_REGISTRATION_INFO, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ // Do not log function arg for privacy
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ }
+
+ android.hardware.radio.ims.ImsRegistration registrationInfo =
+ new android.hardware.radio.ims.ImsRegistration();
+ registrationInfo.state = state;
+ registrationInfo.ipcan = ipcan;
+ registrationInfo.reason = reason;
+ registrationInfo.features = features;
+
+ try {
+ imsProxy.updateImsRegistrationInfo(rr.mSerial, registrationInfo);
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(IMS_SERVICE, "updateImsRegistrationInfo", e);
+ }
+ } else {
+ if (RILJ_LOGD) {
+ Rlog.d(RILJ_LOG_TAG, "updateImsRegistrationInfo: REQUEST_NOT_SUPPORTED");
+ }
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ public void notifyImsTraffic(int token, int trafficType, boolean isStart, Message result) {
+ RadioImsProxy imsProxy = getRadioServiceProxy(RadioImsProxy.class, result);
+ if (imsProxy.isEmpty()) return;
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_1)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_NOTIFY_IMS_TRAFFIC, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ }
+
+ try {
+ imsProxy.notifyImsTraffic(rr.mSerial, token, trafficType, isStart);
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(IMS_SERVICE, "notifyImsTraffic", e);
+ }
+ } else {
+ if (RILJ_LOGD) {
+ Rlog.d(RILJ_LOG_TAG, "notifyImsTraffic: REQUEST_NOT_SUPPORTED");
+ }
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ public void performAcbCheck(int token, int trafficType, Message result) {
+ RadioImsProxy imsProxy = getRadioServiceProxy(RadioImsProxy.class, result);
+ if (imsProxy.isEmpty()) return;
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_2_1)) {
+ RILRequest rr = obtainRequest(RIL_REQUEST_PERFORM_ACB_CHECK, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ }
+
+ try {
+ imsProxy.performAcbCheck(rr.mSerial, token, trafficType);
+ } catch (RemoteException | RuntimeException e) {
+ handleRadioProxyExceptionForRR(IMS_SERVICE, "performAcbCheck", e);
+ }
+ } else {
+ if (RILJ_LOGD) {
+ Rlog.d(RILJ_LOG_TAG, "performAcbCheck: REQUEST_NOT_SUPPORTED");
+ }
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ }
+ }
+
//***** Private Methods
/**
* This is a helper function to be called when an indication callback is called for any radio
@@ -5957,6 +6114,8 @@
return "SIM";
case VOICE_SERVICE:
return "VOICE";
+ case IMS_SERVICE:
+ return "IMS";
default:
return "UNKNOWN:" + service;
}
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 2d1107c..dc13cd4 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -116,6 +116,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_VONR_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_NOTIFY_IMS_TRAFFIC;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_NV_READ_ITEM;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_NV_RESET_CONFIG;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_NV_WRITE_CDMA_PRL;
@@ -123,6 +124,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OEM_HOOK_RAW;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OEM_HOOK_STRINGS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_OPERATOR;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_PERFORM_ACB_CHECK;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_PULL_LCEDATA;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_AVAILABLE_NETWORKS;
@@ -168,6 +170,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SMSC_ADDRESS;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SRVCC_CALL_INFO;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SYSTEM_SELECTION_CHANNELS;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_TTY_MODE;
@@ -200,10 +203,12 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_UDUB;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_UPDATE_IMS_REGISTRATION_INFO;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORD;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_VOICE_RADIO_TECH;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_VOICE_REGISTRATION_STATE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_WRITE_SMS_TO_SIM;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ACCESS_ALLOWED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_BARRING_INFO_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CALL_RING;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION;
@@ -214,6 +219,7 @@
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CELL_INFO_LIST;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CONNECTION_SETUP_FAILURE;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_DATA_CALL_LIST_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_DC_RT_INFO_CHANGED;
import static com.android.internal.telephony.RILConstants.RIL_UNSOL_EMERGENCY_NUMBER_LIST;
@@ -5042,6 +5048,14 @@
return "SET_USAGE_SETTING";
case RIL_REQUEST_GET_USAGE_SETTING:
return "GET_USAGE_SETTING";
+ case RIL_REQUEST_SET_SRVCC_CALL_INFO:
+ return "SET_SRVCC_CALL_INFO";
+ case RIL_REQUEST_UPDATE_IMS_REGISTRATION_INFO:
+ return "UPDATE_IMS_REGISTRATION_INFO";
+ case RIL_REQUEST_NOTIFY_IMS_TRAFFIC:
+ return "NOTIFY_IMS_TRAFFIC";
+ case RIL_REQUEST_PERFORM_ACB_CHECK:
+ return "PERFORM_ACB_CHECK";
default:
return "<unknown request " + request + ">";
}
@@ -5174,6 +5188,10 @@
return "UNSOL_REGISTRATION_FAILED";
case RIL_UNSOL_BARRING_INFO_CHANGED:
return "UNSOL_BARRING_INFO_CHANGED";
+ case RIL_UNSOL_ACCESS_ALLOWED:
+ return "UNSOL_ACCESS_ALLOWED";
+ case RIL_UNSOL_CONNECTION_SETUP_FAILURE:
+ return "UNSOL_CONNECTION_SETUP_FAILURE";
default:
return "<unknown response>";
}
@@ -5322,6 +5340,82 @@
return sb.toString();
}
+ /**
+ * Converts the list of call information for Single Radio Voice Call Continuity(SRVCC).
+ *
+ * @param srvccConnections The list of call information for SRVCC.
+ * @return The converted list of call information.
+ */
+ public static android.hardware.radio.ims.SrvccCall[] convertToHalSrvccCall(
+ SrvccConnection[] srvccConnections) {
+ if (srvccConnections == null) {
+ return new android.hardware.radio.ims.SrvccCall[0];
+ }
+
+ int length = srvccConnections.length;
+ android.hardware.radio.ims.SrvccCall[] srvccCalls =
+ new android.hardware.radio.ims.SrvccCall[length];
+
+ for (int i = 0; i < length; i++) {
+ srvccCalls[i] = new android.hardware.radio.ims.SrvccCall();
+ srvccCalls[i].index = i + 1;
+ srvccCalls[i].callType = srvccConnections[i].getType();
+ srvccCalls[i].callState = convertCallState(srvccConnections[i].getState());
+ srvccCalls[i].callSubstate = srvccConnections[i].getSubState();
+ srvccCalls[i].ringbackToneType = srvccConnections[i].getRingbackToneType();
+ srvccCalls[i].isMpty = srvccConnections[i].isMultiParty();
+ srvccCalls[i].isMT = srvccConnections[i].isIncoming();
+ srvccCalls[i].number = TextUtils.emptyIfNull(srvccConnections[i].getNumber());
+ srvccCalls[i].numPresentation =
+ convertPresentation(srvccConnections[i].getNumberPresentation());
+ srvccCalls[i].name = TextUtils.emptyIfNull(srvccConnections[i].getName());
+ srvccCalls[i].namePresentation =
+ convertPresentation(srvccConnections[i].getNamePresentation());
+ }
+
+ return srvccCalls;
+ }
+
+ /**
+ * Converts the call state.
+ *
+ * @param state The call state.
+ * @return The converted call state.
+ */
+ public static int convertCallState(Call.State state) {
+ switch (state) {
+ case ACTIVE: return android.hardware.radio.voice.Call.STATE_ACTIVE;
+ case HOLDING: return android.hardware.radio.voice.Call.STATE_HOLDING;
+ case DIALING: return android.hardware.radio.voice.Call.STATE_DIALING;
+ case ALERTING: return android.hardware.radio.voice.Call.STATE_ALERTING;
+ case INCOMING: return android.hardware.radio.voice.Call.STATE_INCOMING;
+ case WAITING: return android.hardware.radio.voice.Call.STATE_WAITING;
+ default:
+ throw new RuntimeException("illegal state " + state);
+ }
+ }
+
+ /**
+ * Converts the number presentation type for caller id display.
+ *
+ * @param presentation The number presentation type.
+ * @return The converted presentation type.
+ */
+ public static int convertPresentation(int presentation) {
+ switch (presentation) {
+ case PhoneConstants.PRESENTATION_ALLOWED:
+ return android.hardware.radio.voice.Call.PRESENTATION_ALLOWED;
+ case PhoneConstants.PRESENTATION_RESTRICTED:
+ return android.hardware.radio.voice.Call.PRESENTATION_RESTRICTED;
+ case PhoneConstants.PRESENTATION_UNKNOWN:
+ return android.hardware.radio.voice.Call.PRESENTATION_UNKNOWN;
+ case PhoneConstants.PRESENTATION_PAYPHONE:
+ return android.hardware.radio.voice.Call.PRESENTATION_PAYPHONE;
+ default:
+ throw new RuntimeException("illegal presentation " + presentation);
+ }
+ }
+
private static void logd(String log) {
Rlog.d("RILUtils", log);
}
diff --git a/src/java/com/android/internal/telephony/RadioImsProxy.java b/src/java/com/android/internal/telephony/RadioImsProxy.java
new file mode 100644
index 0000000..e3f3b16
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioImsProxy.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.RemoteException;
+import android.telephony.Rlog;
+
+/**
+ * A holder for IRadioIms.
+ * Use getAidl to get IRadioIms and call the AIDL implementations of the HAL APIs.
+ */
+public class RadioImsProxy extends RadioServiceProxy {
+ private static final String TAG = "RadioImsProxy";
+ private volatile android.hardware.radio.ims.IRadioIms mImsProxy = null;
+
+ /**
+ * Sets IRadioIms as the AIDL implementation for RadioServiceProxy.
+ * @param halVersion Radio HAL version.
+ * @param ims IRadioIms implementation.
+ */
+ public void setAidl(HalVersion halVersion, android.hardware.radio.ims.IRadioIms ims) {
+ mHalVersion = halVersion;
+ mImsProxy = ims;
+ mIsAidl = true;
+ Rlog.d(TAG, "AIDL initialized");
+ }
+
+ /**
+ * Gets the AIDL implementation of RadioImsProxy.
+ * @return IRadioIms implementation.
+ */
+ public android.hardware.radio.ims.IRadioIms getAidl() {
+ return mImsProxy;
+ }
+
+ /**
+ * Resets RadioImsProxy.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ mImsProxy = null;
+ }
+
+ /**
+ * Checks whether a RadioIms implementation exists.
+ * @return true if there is neither a HIDL nor AIDL implementation.
+ */
+ @Override
+ public boolean isEmpty() {
+ return mRadioProxy == null && mImsProxy == null;
+ }
+
+ /**
+ * No implementation in IRadioIms.
+ * @throws RemoteException.
+ */
+ @Override
+ public void responseAcknowledgement() throws RemoteException {
+ /* Currently, IRadioIms doesn't support the following response types:
+ * - RadioIndicationType.UNSOLICITED_ACK_EXP
+ * - RadioResponseType.SOLICITED_ACK_EXP */
+ // no-op
+ }
+
+ /**
+ * Calls IRadioIms#setSrvccCallInfo.
+ * @param serial Serial number of request.
+ * @param srvccCalls The list of call information.
+ * @throws RemoteException.
+ */
+ public void setSrvccCallInfo(int serial,
+ android.hardware.radio.ims.SrvccCall[] srvccCalls) throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mImsProxy.setSrvccCallInfo(serial, srvccCalls);
+ }
+ }
+
+ /**
+ * Calls IRadioIms#updateImsRegistrationInfo.
+ * @param serial Serial number of request.
+ * @param registrationInfo The registration state information.
+ * @throws RemoteException.
+ */
+ public void updateImsRegistrationInfo(int serial,
+ android.hardware.radio.ims.ImsRegistration registrationInfo) throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mImsProxy.updateImsRegistrationInfo(serial, registrationInfo);
+ }
+ }
+
+ /**
+ * Calls IRadioIms#startImsTraffic.
+ * @param serial Serial number of request.
+ * @throws RemoteException.
+ */
+ public void notifyImsTraffic(int serial, int token, int trafficType, boolean isStart)
+ throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mImsProxy.notifyImsTraffic(serial, token, trafficType, isStart);
+ }
+ }
+
+ /**
+ * Calls IRadioIms#performAcbCheck.
+ * @param serial Serial number of request.
+ * @throws RemoteException.
+ */
+ public void performAcbCheck(int serial, int token, int trafficType) throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mImsProxy.performAcbCheck(serial, token, trafficType);
+ }
+ }
+}
diff --git a/src/java/com/android/internal/telephony/SrvccConnection.java b/src/java/com/android/internal/telephony/SrvccConnection.java
new file mode 100644
index 0000000..b491b51
--- /dev/null
+++ b/src/java/com/android/internal/telephony/SrvccConnection.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Connection information for SRVCC
+ */
+public class SrvccConnection {
+ private static final String TAG = "SrvccConnection";
+
+ private static final int CALL_TYPE_NORMAL = 0;
+ private static final int CALL_TYPE_EMERGENCY = 1;
+
+ public static final int SUBSTATE_NONE = 0;
+ /** Pre-alerting state. Applicable for MT calls only */
+ public static final int SUBSTATE_PREALERTING = 1;
+
+ public static final int TONE_NONE = 0;
+ public static final int TONE_LOCAL = 1;
+ public static final int TONE_NETWORK = 2;
+
+ /** Values are CALL_TYPE_ */
+ private int mType;
+
+ /** Values are Call.State */
+ private Call.State mState;
+
+ /** Values are SUBSTATE_ */
+ private int mSubstate;
+
+ /** Values are TONE_ */
+ private int mRingbackToneType;
+
+ /** true if it is a multi-party call */
+ private boolean mIsMpty;
+
+ /** true if it is a mobile terminated call */
+ private boolean mIsMT;
+
+ /** Remote party nummber */
+ private String mNumber;
+
+ /** Values are PhoneConstants.PRESENTATION_ */
+ private int mNumPresentation;
+
+ /** Remote party name */
+ private String mName;
+
+ /** Values are PhoneConstants.PRESENTATION_ */
+ private int mNamePresentation;
+
+ public SrvccConnection(Connection c, boolean isEmergency, int ringbackToneType) {
+ mType = isEmergency ? CALL_TYPE_EMERGENCY : CALL_TYPE_NORMAL;
+ mState = c.getState();
+ mSubstate = SUBSTATE_NONE;
+ mRingbackToneType = ringbackToneType;
+ mIsMpty = false;
+ mIsMT = c.isIncoming();
+ mNumber = c.getAddress();
+ mNumPresentation = c.getNumberPresentation();
+ mName = c.getCnapName();
+ mNamePresentation = c.getCnapNamePresentation();
+ }
+
+ /** Returns the type of the call */
+ public int getType() {
+ return mType;
+ }
+
+ /** Returns the state */
+ public Call.State getState() {
+ return mState;
+ }
+
+ /** Returns the sub state */
+ public int getSubState() {
+ return mSubstate;
+ }
+
+ /** Returns the ringback tone type */
+ public int getRingbackToneType() {
+ return mRingbackToneType;
+ }
+
+ /** true if it is a multi-party call */
+ public boolean isMultiParty() {
+ return mIsMpty;
+ }
+
+ /** true if it is a mobile terminated call */
+ public boolean isIncoming() {
+ return mIsMT;
+ }
+
+ /** Returns the remote party nummber */
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /** Returns the number presentation */
+ public int getNumberPresentation() {
+ return mNumPresentation;
+ }
+
+ /** Returns the remote party name */
+ public String getName() {
+ return mName;
+ }
+
+ /** Returns the name presentation */
+ public int getNamePresentation() {
+ return mNamePresentation;
+ }
+}