diff options
13 files changed, 1233 insertions, 89 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 2e4043654d44..ef3a54387d25 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11153,10 +11153,11 @@ package android.telephony.ims { } public interface DelegateStateCallback { + method public void onConfigurationChanged(@NonNull android.telephony.ims.SipDelegateConfiguration); method public void onCreated(@NonNull android.telephony.ims.stub.SipDelegate, @Nullable java.util.Set<android.telephony.ims.FeatureTagState>); method public void onDestroyed(int); method public void onFeatureTagRegistrationChanged(@NonNull android.telephony.ims.DelegateRegistrationState); - method public void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration); + method @Deprecated public void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration); } public final class FeatureTagState implements android.os.Parcelable { @@ -11895,6 +11896,76 @@ package android.telephony.ims { field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RtpHeaderExtensionType> CREATOR; } + public final class SipDelegateConfiguration implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getHomeDomain(); + method @Nullable public String getImei(); + method @Nullable public android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration getIpSecConfiguration(); + method @NonNull public java.net.InetSocketAddress getLocalAddress(); + method public int getMaxUdpPayloadSizeBytes(); + method @Nullable public java.net.InetSocketAddress getNatSocketAddress(); + method @Nullable public String getPrivateUserIdentifier(); + method @Nullable public android.net.Uri getPublicGruuUri(); + method @Nullable public String getPublicUserIdentifier(); + method @Nullable public String getSipAssociatedUriHeader(); + method @Nullable public String getSipAuthenticationHeader(); + method @Nullable public String getSipAuthenticationNonce(); + method @Nullable public String getSipCniHeader(); + method @Nullable public String getSipContactUserParameter(); + method @Nullable public String getSipPaniHeader(); + method @Nullable public String getSipPathHeader(); + method @Nullable public String getSipPlaniHeader(); + method @NonNull public java.net.InetSocketAddress getSipServerAddress(); + method @Nullable public String getSipServiceRouteHeader(); + method @Nullable public String getSipUserAgentHeader(); + method public int getTransportType(); + method @IntRange(from=0) public long getVersion(); + method public boolean isSipCompactFormEnabled(); + method public boolean isSipKeepaliveEnabled(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipDelegateConfiguration> CREATOR; + field public static final int SIP_TRANSPORT_TCP = 1; // 0x1 + field public static final int SIP_TRANSPORT_UDP = 0; // 0x0 + field public static final int UDP_PAYLOAD_SIZE_UNDEFINED = -1; // 0xffffffff + } + + public static final class SipDelegateConfiguration.Builder { + ctor public SipDelegateConfiguration.Builder(@IntRange(from=0) long, int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); + ctor public SipDelegateConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateConfiguration); + method @NonNull public android.telephony.ims.SipDelegateConfiguration build(); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setHomeDomain(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setImei(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setIpSecConfiguration(@Nullable android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setMaxUdpPayloadSizeBytes(@IntRange(from=1) int); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setNatSocketAddress(@Nullable java.net.InetSocketAddress); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setPrivateUserIdentifier(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setPublicGruuUri(@Nullable android.net.Uri); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setPublicUserIdentifier(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipAssociatedUriHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipAuthenticationHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipAuthenticationNonce(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipCniHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipCompactFormEnabled(boolean); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipContactUserParameter(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipKeepaliveEnabled(boolean); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipPaniHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipPathHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipPlaniHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipServiceRouteHeader(@Nullable String); + method @NonNull public android.telephony.ims.SipDelegateConfiguration.Builder setSipUserAgentHeader(@Nullable String); + } + + public static final class SipDelegateConfiguration.IpSecConfiguration { + ctor public SipDelegateConfiguration.IpSecConfiguration(int, int, int, int, int, int, @NonNull String); + method public int getLastLocalTxPort(); + method public int getLastRemoteTxPort(); + method public int getLocalRxPort(); + method public int getLocalTxPort(); + method public int getRemoteRxPort(); + method public int getRemoteTxPort(); + method @NonNull public String getSipSecurityVerifyHeader(); + } + public interface SipDelegateConnection { method public default void cleanupSession(@NonNull String); method @Deprecated public default void closeDialog(@NonNull String); @@ -11903,65 +11974,65 @@ package android.telephony.ims { method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long); } - public final class SipDelegateImsConfiguration implements android.os.Parcelable { - method public boolean containsKey(@NonNull String); - method @NonNull public android.os.PersistableBundle copyBundle(); - method public int describeContents(); - method public boolean getBoolean(@NonNull String, boolean); - method public int getInt(@NonNull String, int); - method @Nullable public String getString(@NonNull String); - method public long getVersion(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipDelegateImsConfiguration> CREATOR; - field public static final String IPTYPE_IPV4 = "IPV4"; - field public static final String IPTYPE_IPV6 = "IPV6"; - field public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING = "sip_config_auhentication_header_string"; - field public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING = "sip_config_authentication_nonce_string"; - field public static final String KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING = "sip_config_cellular_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string"; - field public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string"; - field public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string"; - field public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL = "sip_config_is_compact_form_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL = "sip_config_is_gruu_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL = "sip_config_is_ipsec_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL = "sip_config_is_keepalive_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL = "sip_config_is_nat_enabled_bool"; - field public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT = "sip_config_udp_max_payload_size_int"; - field public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING = "sip_config_path_header_string"; - field public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_access_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING = "sip_config_p_associated_uri_header_string"; - field public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_last_access_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING = "sip_config_security_verify_header_string"; - field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING = "sip_config_server_default_ipaddress_string"; - field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT = "sip_config_server_default_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT = "sip_config_server_ipsec_client_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_server_ipsec_old_client_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT = "sip_config_server_ipsec_server_port_int"; - field public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING = "sip_config_service_route_header_string"; - field public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING = "sip_config_protocol_type_string"; - field public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING = "sip_config_ue_default_ipaddress_string"; - field public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT = "sip_config_ue_default_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT = "sip_config_ue_ipsec_client_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_ue_ipsec_old_client_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT = "sip_config_ue_ipsec_server_port_int"; - field public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING = "sip_config_ue_private_user_id_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING = "sip_config_ue_public_gruu_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING = "sip_config_ue_public_ipaddress_with_nat_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT = "sip_config_ue_public_port_with_nat_int"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING = "sip_config_ue_public_user_id_string"; - field public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING = "sip_config_uri_user_part_string"; - field public static final String KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING = "sip_config_sip_user_agent_header_string"; - field public static final String SIP_TRANSPORT_TCP = "TCP"; - field public static final String SIP_TRANSPORT_UDP = "UDP"; - } - - public static final class SipDelegateImsConfiguration.Builder { - ctor public SipDelegateImsConfiguration.Builder(int); - ctor public SipDelegateImsConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateImsConfiguration); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addBoolean(@NonNull String, boolean); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addInt(@NonNull String, int); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addString(@NonNull String, @NonNull String); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration build(); + @Deprecated public final class SipDelegateImsConfiguration implements android.os.Parcelable { + method @Deprecated public boolean containsKey(@NonNull String); + method @Deprecated @NonNull public android.os.PersistableBundle copyBundle(); + method @Deprecated public int describeContents(); + method @Deprecated public boolean getBoolean(@NonNull String, boolean); + method @Deprecated public int getInt(@NonNull String, int); + method @Deprecated @Nullable public String getString(@NonNull String); + method @Deprecated public long getVersion(); + method @Deprecated public void writeToParcel(@NonNull android.os.Parcel, int); + field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipDelegateImsConfiguration> CREATOR; + field @Deprecated public static final String IPTYPE_IPV4 = "IPV4"; + field @Deprecated public static final String IPTYPE_IPV6 = "IPV6"; + field @Deprecated public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING = "sip_config_auhentication_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING = "sip_config_authentication_nonce_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING = "sip_config_cellular_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL = "sip_config_is_compact_form_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL = "sip_config_is_gruu_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL = "sip_config_is_ipsec_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL = "sip_config_is_keepalive_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL = "sip_config_is_nat_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT = "sip_config_udp_max_payload_size_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING = "sip_config_path_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_access_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING = "sip_config_p_associated_uri_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_last_access_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING = "sip_config_security_verify_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING = "sip_config_server_default_ipaddress_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT = "sip_config_server_default_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT = "sip_config_server_ipsec_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_server_ipsec_old_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT = "sip_config_server_ipsec_server_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING = "sip_config_service_route_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING = "sip_config_protocol_type_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING = "sip_config_ue_default_ipaddress_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT = "sip_config_ue_default_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT = "sip_config_ue_ipsec_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_ue_ipsec_old_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT = "sip_config_ue_ipsec_server_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING = "sip_config_ue_private_user_id_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING = "sip_config_ue_public_gruu_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING = "sip_config_ue_public_ipaddress_with_nat_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT = "sip_config_ue_public_port_with_nat_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING = "sip_config_ue_public_user_id_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING = "sip_config_uri_user_part_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING = "sip_config_sip_user_agent_header_string"; + field @Deprecated public static final String SIP_TRANSPORT_TCP = "TCP"; + field @Deprecated public static final String SIP_TRANSPORT_UDP = "UDP"; + } + + @Deprecated public static final class SipDelegateImsConfiguration.Builder { + ctor @Deprecated public SipDelegateImsConfiguration.Builder(int); + ctor @Deprecated public SipDelegateImsConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateImsConfiguration); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addBoolean(@NonNull String, boolean); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addInt(@NonNull String, int); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addString(@NonNull String, @NonNull String); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration build(); } public class SipDelegateManager { @@ -12131,10 +12202,11 @@ package android.telephony.ims.stub { } public interface DelegateConnectionStateCallback { + method public default void onConfigurationChanged(@NonNull android.telephony.ims.SipDelegateConfiguration); method public void onCreated(@NonNull android.telephony.ims.SipDelegateConnection); method public void onDestroyed(int); method public void onFeatureTagStatusChanged(@NonNull android.telephony.ims.DelegateRegistrationState, @NonNull java.util.Set<android.telephony.ims.FeatureTagState>); - method public void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration); + method @Deprecated public default void onImsConfigurationChanged(@NonNull android.telephony.ims.SipDelegateImsConfiguration); } public class ImsCallSessionImplBase implements java.lang.AutoCloseable { diff --git a/telephony/java/android/telephony/ims/DelegateStateCallback.java b/telephony/java/android/telephony/ims/DelegateStateCallback.java index 6bf992e64480..2b4fb7d5cbf3 100644 --- a/telephony/java/android/telephony/ims/DelegateStateCallback.java +++ b/telephony/java/android/telephony/ims/DelegateStateCallback.java @@ -79,10 +79,30 @@ public interface DelegateStateCallback { * messages routing should be delayed until the {@link SipDelegate} sends the IMS configuration * change event to reduce conditions where the remote application is using a stale IMS * configuration. + * @deprecated This is being removed from API surface, Use + * {@link #onConfigurationChanged(SipDelegateConfiguration)} instead. */ + @Deprecated void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config); /** + * Call to notify the remote application of a configuration change associated with this + * {@link SipDelegate}. + * <p> + * The remote application will not be able to proceed sending SIP messages until after this + * configuration is sent the first time, so this configuration should be sent as soon as the + * {@link SipDelegate} has access to these configuration parameters. + * <p> + * Incoming SIP messages should not be routed to the remote application until AFTER this + * configuration change is sent to ensure that the remote application can respond correctly. + * Similarly, if there is an event that triggers the IMS configuration to change, incoming SIP + * messages routing should be delayed until the {@link SipDelegate} sends the IMS configuration + * change event to reduce conditions where the remote application is using a stale IMS + * configuration. + */ + void onConfigurationChanged(@NonNull SipDelegateConfiguration config); + + /** * Call to notify the remote application that the {@link SipDelegate} has modified the IMS * registration state of the RCS feature tags that were requested as part of the initial * {@link DelegateRequest}. diff --git a/telephony/java/android/telephony/ims/SipDelegateConfiguration.aidl b/telephony/java/android/telephony/ims/SipDelegateConfiguration.aidl new file mode 100644 index 000000000000..2fc9c48fb9fc --- /dev/null +++ b/telephony/java/android/telephony/ims/SipDelegateConfiguration.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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 android.telephony.ims; + +parcelable SipDelegateConfiguration; diff --git a/telephony/java/android/telephony/ims/SipDelegateConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java new file mode 100644 index 000000000000..1bf5cad49c53 --- /dev/null +++ b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java @@ -0,0 +1,932 @@ +/* + * Copyright (C) 2021 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 android.telephony.ims; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.InetAddresses; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.ims.stub.SipDelegate; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +/** + * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the + * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s. + * <p> + * The IMS service must generate new instances of this configuration as the IMS configuration + * managed by the IMS service changes. Along with each {@link SipDelegateConfiguration} instance + * containing the configuration is the "version", which should be incremented every time a new + * {@link SipDelegateConfiguration} instance is created. The {@link SipDelegateConnection} will + * include the version of the {@link SipDelegateConfiguration} instance that it used in order for + * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration + * to generate the {@link SipMessage} and return + * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in + * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can + * regenerate that {@link SipMessage} using the correct {@link SipDelegateConfiguration} + * instance. + * <p> + * Every time the IMS configuration state changes in the IMS service, a full configuration should + * be generated. The new {@link SipDelegateConfiguration} instance should not be an incremental + * update. + * @see Builder + * @hide + */ +@SystemApi +public final class SipDelegateConfiguration implements Parcelable { + + /** + * The SIP transport uses UDP. + */ + public static final int SIP_TRANSPORT_UDP = 0; + + /** + * The SIP transport uses TCP. + */ + public static final int SIP_TRANSPORT_TCP = 1; + + /**@hide*/ + @IntDef(prefix = "SIP_TRANSPORT_", value = { + SIP_TRANSPORT_UDP, + SIP_TRANSPORT_TCP + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TransportType {} + + /** + * The value returned by {@link #getMaxUdpPayloadSizeBytes()} when it is not defined. + */ + public static final int UDP_PAYLOAD_SIZE_UNDEFINED = -1; + + /** + * SIP over IPSec configuration + */ + public static final class IpSecConfiguration { + private final int mLocalTxPort; + private final int mLocalRxPort; + private final int mLastLocalTxPort; + private final int mRemoteTxPort; + private final int mRemoteRxPort; + private final int mLastRemoteTxPort; + private final String mSecurityHeader; + + /** + * Describes the SIP over IPSec configuration the SipDelegate will need to use. + * + * @param localTxPort Local SIP port number used to send traffic. + * @param localRxPort Local SIP port number used to receive traffic. + * @param lastLocalTxPort Local SIP port number used for the previous IPsec security + * association. + * @param remoteTxPort Remote port number used by the SIP server to send SIP traffic. + * @param remoteRxPort Remote port number used by the SIP server to receive incoming SIP + * traffic. + * @param lastRemoteTxPort Remote port number used by the SIP server to send SIP traffic on + * the previous IPSec security association. + * @param securityHeader The value of the SIP security verify header. + */ + public IpSecConfiguration(int localTxPort, int localRxPort, int lastLocalTxPort, + int remoteTxPort, int remoteRxPort, int lastRemoteTxPort, + @NonNull String securityHeader) { + mLocalTxPort = localTxPort; + mLocalRxPort = localRxPort; + mLastLocalTxPort = lastLocalTxPort; + mRemoteTxPort = remoteTxPort; + mRemoteRxPort = remoteRxPort; + mLastRemoteTxPort = lastRemoteTxPort; + mSecurityHeader = securityHeader; + } + + /** + * @return The local SIP port number used to send traffic. + */ + public int getLocalTxPort() { + return mLocalTxPort; + } + + /** + * @return The Local SIP port number used to receive traffic. + */ + public int getLocalRxPort() { + return mLocalRxPort; + } + + /** + * @return The last local SIP port number used for the previous IPsec security association. + */ + public int getLastLocalTxPort() { + return mLastLocalTxPort; + } + + /** + * @return The remote port number used by the SIP server to send SIP traffic. + */ + public int getRemoteTxPort() { + return mRemoteTxPort; + } + + /** + * @return the remote port number used by the SIP server to receive incoming SIP traffic. + */ + public int getRemoteRxPort() { + return mRemoteRxPort; + } + + /** + * @return the remote port number used by the SIP server to send SIP traffic on the previous + * IPSec security association. + */ + public int getLastRemoteTxPort() { + return mLastRemoteTxPort; + } + + /** + * @return The value of the SIP security verify header. + */ + public @NonNull String getSipSecurityVerifyHeader() { + return mSecurityHeader; + } + + /** + * Helper for parcelling this object. + * @hide + */ + public void addToParcel(Parcel dest) { + dest.writeInt(mLocalTxPort); + dest.writeInt(mLocalRxPort); + dest.writeInt(mLastLocalTxPort); + dest.writeInt(mRemoteTxPort); + dest.writeInt(mRemoteRxPort); + dest.writeInt(mLastRemoteTxPort); + dest.writeString(mSecurityHeader); + } + + /** + * Helper for unparcelling this object. + * @hide + */ + public static IpSecConfiguration fromParcel(Parcel source) { + return new IpSecConfiguration(source.readInt(), source.readInt(), source.readInt(), + source.readInt(), source.readInt(), source.readInt(), source.readString()); + } + + @Override + public String toString() { + return "IpSecConfiguration{" + "localTx=" + mLocalTxPort + ", localRx=" + mLocalRxPort + + ", lastLocalTx=" + mLastLocalTxPort + ", remoteTx=" + mRemoteTxPort + + ", remoteRx=" + mRemoteRxPort + ", lastRemoteTx=" + mLastRemoteTxPort + + ", securityHeader=" + mSecurityHeader + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IpSecConfiguration that = (IpSecConfiguration) o; + return mLocalTxPort == that.mLocalTxPort + && mLocalRxPort == that.mLocalRxPort + && mLastLocalTxPort == that.mLastLocalTxPort + && mRemoteTxPort == that.mRemoteTxPort + && mRemoteRxPort == that.mRemoteRxPort + && mLastRemoteTxPort == that.mLastRemoteTxPort + && Objects.equals(mSecurityHeader, that.mSecurityHeader); + } + + @Override + public int hashCode() { + return Objects.hash(mLocalTxPort, mLocalRxPort, mLastLocalTxPort, mRemoteTxPort, + mRemoteRxPort, mLastRemoteTxPort, mSecurityHeader); + } + } + + /** + * Creates a new instance of {@link SipDelegateConfiguration} composed from optional + * configuration items. + */ + public static final class Builder { + private final SipDelegateConfiguration mConfig; + + /** + * + * @param version The version associated with the {@link SipDelegateConfiguration} instance + * being built. See {@link #getVersion()} for more information. + * @param transportType The transport type to use for SIP signalling. + * @param localAddr The local socket address used for SIP traffic. + * @param serverAddr The SIP server or P-CSCF default IP address for sip traffic. + * @see InetAddresses#parseNumericAddress(String) for how to create an + * {@link InetAddress} without requiring a DNS lookup. + */ + public Builder(@IntRange(from = 0) long version, @TransportType int transportType, + @NonNull InetSocketAddress localAddr, @NonNull InetSocketAddress serverAddr) { + mConfig = new SipDelegateConfiguration(version, transportType, localAddr, + serverAddr); + } + + /** + * Create a new {@link SipDelegateConfiguration} instance with the same exact configuration + * as the passed in instance, except for the version parameter, which will be incremented + * by 1. + * <p> + * This method is useful for cases where only a small subset of configurations have changed + * and the new configuration is based off of the old configuration. + * @param c The older {@link SipDelegateConfiguration} instance to base this instance's + * configuration off of. + */ + public Builder(@NonNull SipDelegateConfiguration c) { + mConfig = c.copyAndIncrementVersion(); + } + + /** + * Sets whether or not SIP compact form is enabled for the associated SIP delegate. + * <p> + * If unset, this configuration defaults to {@code false}. + * @param isEnabled {@code true} if SIP compact form is enabled for the associated SIP + * Delegate, {@code false} if it is not. + * @return this Builder instance with the compact form configuration set. + */ + public @NonNull Builder setSipCompactFormEnabled(boolean isEnabled) { + mConfig.mIsSipCompactFormEnabled = isEnabled; + return this; + } + + /** + * Sets whether or not underlying SIP keepalives are enabled for the associated SIP + * delegate. + * <p> + * If unset, this configuration defaults to {@code false}. + * @param isEnabled {@code true} if SIP keepalives are enabled for the associated SIP + * Delegate, {@code false} if it is not. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setSipKeepaliveEnabled(boolean isEnabled) { + mConfig.mIsSipKeepaliveEnabled = isEnabled; + return this; + } + + /** + * Sets the max SIP payload size in bytes to be sent on UDP. If the SIP message payload is + * greater than the max UDP payload size, then TCP must be used. + * <p> + * If unset, this configuration defaults to {@link #UDP_PAYLOAD_SIZE_UNDEFINED}, or no + * size specified. + * @param size The maximum SIP payload size in bytes for UDP. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setMaxUdpPayloadSizeBytes(@IntRange(from = 1) int size) { + mConfig.mMaxUdpPayloadSize = size; + return this; + } + + /** + * Sets the IMS public user identifier. + * <p> + * If unset, this configuration defaults to {@code null}, or no identifier specified. + * @param id The IMS public user identifier. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setPublicUserIdentifier(@Nullable String id) { + mConfig.mPublicUserIdentifier = id; + return this; + } + + /** + * Sets the IMS private user identifier. + * <p> + * If unset, this configuration defaults to {@code null}, or no identifier specified. + * @param id The IMS private user identifier. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setPrivateUserIdentifier(@Nullable String id) { + mConfig.mPrivateUserIdentifier = id; + return this; + } + + /** + * Sets the IMS home domain. + * <p> + * If unset, this configuration defaults to {@code null}, or no domain specified. + * @param domain The IMS home domain. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setHomeDomain(@Nullable String domain) { + mConfig.mHomeDomain = domain; + return this; + } + + /** + * Sets the IMEI of the associated device. + * <p> + * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the + * Contact header with a value of the device IMEI in the form + * {@code "urn:gsma:imei:<device IMEI>"}. + * <p> + * If unset, this configuration defaults to {@code null}, or no IMEI string specified. + * @param imei The IMEI of the device. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setImei(@Nullable String imei) { + mConfig.mImei = imei; + return this; + } + + /** + * Set the optional {@link IpSecConfiguration} instance used if the associated SipDelegate + * is communicating over IPSec. + * <p> + * If unset, this configuration defaults to {@code null} + * @param c The IpSecConfiguration instance to set. + * @return this Builder instance with IPSec configuration set. + */ + public @NonNull Builder setIpSecConfiguration(@Nullable IpSecConfiguration c) { + mConfig.mIpSecConfiguration = c; + return this; + } + + /** + * Describes the Device's Public IP Address and port that is set when Network Address + * Translation is enabled and the device is behind a NAT. + * <p> + * If unset, this configuration defaults to {@code null} + * @param addr The {@link InetAddress} representing the device's public IP address and port + * when behind a NAT. + * @return this Builder instance with the new configuration set. + * @see InetAddresses#parseNumericAddress(String) For an example of how to create an + * instance of {@link InetAddress} without causing a DNS lookup. + */ + public @NonNull Builder setNatSocketAddress(@Nullable InetSocketAddress addr) { + mConfig.mNatAddress = addr; + return this; + } + + /** + * Sets the optional URI of the device's Globally routable user-agent URI (GRUU) if this + * feature is enabled for the SIP delegate. + * <p> + * If unset, this configuration defaults to {@code null} + * @param uri The GRUU to set. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setPublicGruuUri(@Nullable Uri uri) { + mConfig.mGruu = uri; + return this; + } + + /** + * Sets the SIP authentication header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP authentication header's value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAuthenticationHeader(@Nullable String header) { + mConfig.mSipAuthHeader = header; + return this; + } + + /** + * Sets the SIP authentication nonce. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param nonce The SIP authentication nonce. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAuthenticationNonce(@Nullable String nonce) { + mConfig.mSipAuthNonce = nonce; + return this; + } + + /** + * Sets the SIP service route header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP service route header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipServiceRouteHeader(@Nullable String header) { + mConfig.mServiceRouteHeader = header; + return this; + } + + /** + * Sets the SIP path header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP path header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPathHeader(@Nullable String header) { + mConfig.mPathHeader = header; + return this; + } + + /** + * Sets the SIP User-Agent header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP User-Agent header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipUserAgentHeader(@Nullable String header) { + mConfig.mUserAgentHeader = header; + return this; + } + + /** + * Sets the SIP Contact header's User parameter value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param param The SIP Contact header's User parameter value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipContactUserParameter(@Nullable String param) { + mConfig.mContactUserParam = param; + return this; + } + + /** + * Sets the SIP P-Access-Network-Info (P-ANI) header value. Populated for networks that + * require this information to be provided as part of outgoing SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-ANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPaniHeader(@Nullable String header) { + mConfig.mPaniHeader = header; + return this; + } + + /** + * Sets the SIP P-Last-Access-Network-Info (P-LANI) header value. Populated for + * networks that require this information to be provided as part of outgoing SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-LANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPlaniHeader(@Nullable String header) { + mConfig.mPlaniHeader = header; + return this; + } + + /** + * Sets the SIP Cellular-Network-Info (CNI) header value (See 3GPP 24.229, section 7.2.15), + * populated for networks that require this information to be provided as part of outgoing + * SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-LANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipCniHeader(@Nullable String header) { + mConfig.mCniHeader = header; + return this; + } + + /** + * Sets the SIP P-associated-uri header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-associated-uri header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAssociatedUriHeader(@Nullable String header) { + mConfig.mAssociatedUriHeader = header; + return this; + } + + /** + * @return A {@link SipDelegateConfiguration} instance with the optional configurations set. + */ + public @NonNull SipDelegateConfiguration build() { + return mConfig; + } + } + + private final long mVersion; + private final int mTransportType; + private final InetSocketAddress mLocalAddress; + private final InetSocketAddress mSipServerAddress; + private boolean mIsSipCompactFormEnabled = false; + private boolean mIsSipKeepaliveEnabled = false; + private int mMaxUdpPayloadSize = -1; + private String mPublicUserIdentifier = null; + private String mPrivateUserIdentifier = null; + private String mHomeDomain = null; + private String mImei = null; + private Uri mGruu = null; + private String mSipAuthHeader = null; + private String mSipAuthNonce = null; + private String mServiceRouteHeader = null; + private String mPathHeader = null; + private String mUserAgentHeader = null; + private String mContactUserParam = null; + private String mPaniHeader = null; + private String mPlaniHeader = null; + private String mCniHeader = null; + private String mAssociatedUriHeader = null; + private IpSecConfiguration mIpSecConfiguration = null; + private InetSocketAddress mNatAddress = null; + + + private SipDelegateConfiguration(long version, int transportType, + InetSocketAddress localAddress, InetSocketAddress sipServerAddress) { + mVersion = version; + mTransportType = transportType; + mLocalAddress = localAddress; + mSipServerAddress = sipServerAddress; + } + + private SipDelegateConfiguration(Parcel source) { + mVersion = source.readLong(); + mTransportType = source.readInt(); + mLocalAddress = readAddressFromParcel(source); + mSipServerAddress = readAddressFromParcel(source); + mIsSipCompactFormEnabled = source.readBoolean(); + mIsSipKeepaliveEnabled = source.readBoolean(); + mMaxUdpPayloadSize = source.readInt(); + mPublicUserIdentifier = source.readString(); + mPrivateUserIdentifier = source.readString(); + mHomeDomain = source.readString(); + mImei = source.readString(); + mGruu = source.readParcelable(null); + mSipAuthHeader = source.readString(); + mSipAuthNonce = source.readString(); + mServiceRouteHeader = source.readString(); + mPathHeader = source.readString(); + mUserAgentHeader = source.readString(); + mContactUserParam = source.readString(); + mPaniHeader = source.readString(); + mPlaniHeader = source.readString(); + mCniHeader = source.readString(); + mAssociatedUriHeader = source.readString(); + boolean isIpsecConfigAvailable = source.readBoolean(); + if (isIpsecConfigAvailable) { + mIpSecConfiguration = IpSecConfiguration.fromParcel(source); + } + boolean isNatConfigAvailable = source.readBoolean(); + if (isNatConfigAvailable) { + mNatAddress = readAddressFromParcel(source); + } + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeLong(mVersion); + dest.writeInt(mTransportType); + writeAddressToParcel(mLocalAddress, dest); + writeAddressToParcel(mSipServerAddress, dest); + dest.writeBoolean(mIsSipCompactFormEnabled); + dest.writeBoolean(mIsSipKeepaliveEnabled); + dest.writeInt(mMaxUdpPayloadSize); + dest.writeString(mPublicUserIdentifier); + dest.writeString(mPrivateUserIdentifier); + dest.writeString(mHomeDomain); + dest.writeString(mImei); + dest.writeParcelable(mGruu, flags); + dest.writeString(mSipAuthHeader); + dest.writeString(mSipAuthNonce); + dest.writeString(mServiceRouteHeader); + dest.writeString(mPathHeader); + dest.writeString(mUserAgentHeader); + dest.writeString(mContactUserParam); + dest.writeString(mPaniHeader); + dest.writeString(mPlaniHeader); + dest.writeString(mCniHeader); + dest.writeString(mAssociatedUriHeader); + dest.writeBoolean(mIpSecConfiguration != null); + if (mIpSecConfiguration != null) { + mIpSecConfiguration.addToParcel(dest); + } + dest.writeBoolean(mNatAddress != null); + if (mNatAddress != null) { + writeAddressToParcel(mNatAddress, dest); + } + } + + /** + * @return A copy of this instance with an incremented version. + * @hide + */ + public SipDelegateConfiguration copyAndIncrementVersion() { + SipDelegateConfiguration c = new SipDelegateConfiguration(getVersion() + 1, mTransportType, + mLocalAddress, mSipServerAddress); + c.mIsSipCompactFormEnabled = mIsSipCompactFormEnabled; + c.mIsSipKeepaliveEnabled = mIsSipKeepaliveEnabled; + c.mMaxUdpPayloadSize = mMaxUdpPayloadSize; + c.mIpSecConfiguration = mIpSecConfiguration; + c.mNatAddress = mNatAddress; + c.mPublicUserIdentifier = mPublicUserIdentifier; + c.mPrivateUserIdentifier = mPrivateUserIdentifier; + c.mHomeDomain = mHomeDomain; + c.mImei = mImei; + c.mGruu = mGruu; + c.mSipAuthHeader = mSipAuthHeader; + c.mSipAuthNonce = mSipAuthNonce; + c.mServiceRouteHeader = mServiceRouteHeader; + c.mPathHeader = mPathHeader; + c.mUserAgentHeader = mUserAgentHeader; + c.mContactUserParam = mContactUserParam; + c.mPaniHeader = mPaniHeader; + c.mPlaniHeader = mPlaniHeader; + c.mCniHeader = mCniHeader; + c.mAssociatedUriHeader = mAssociatedUriHeader; + return c; + } + + /** + * An integer representing the version number of this SipDelegateImsConfiguration. + * {@link SipMessage}s that are created using this configuration will also have a this + * version number associated with them, which will allow the IMS service to validate that the + * {@link SipMessage} was using the latest configuration during creation and not a stale + * configuration due to race conditions between the configuration being updated and the RCS + * application not receiving the updated configuration before generating a new message. + * <p> + * The version number should be a positive number that starts at 0 and increments sequentially + * as new {@link SipDelegateConfiguration} instances are created to update the IMS + * configuration state. + * + * @return the version number associated with this {@link SipDelegateConfiguration}. + */ + public @IntRange(from = 0) long getVersion() { + return mVersion; + } + + /** + * @return The Transport type of the SIP delegate. + */ + public @TransportType int getTransportType() { + return mTransportType; + } + + /** + * @return The local IP address and port used for SIP traffic. + */ + public @NonNull InetSocketAddress getLocalAddress() { + return mLocalAddress; + } + + /** + * @return The default IP Address and port of the SIP server or P-CSCF used for SIP traffic. + */ + public @NonNull InetSocketAddress getSipServerAddress() { + return mSipServerAddress; + } + + /** + * @return {@code true} if SIP compact form is enabled for the associated SIP Delegate, + * {@code false} if it is not. + */ + public boolean isSipCompactFormEnabled() { + return mIsSipCompactFormEnabled; + } + + /** + * @return {@code true} if SIP keepalives are enabled for the associated SIP Delegate, + * {@code false} if it is not. + */ + public boolean isSipKeepaliveEnabled() { + return mIsSipKeepaliveEnabled; + } + + /** + * @return The maximum SIP payload size in bytes for UDP or {code -1} if no value was set. + */ + public int getMaxUdpPayloadSizeBytes() { + return mMaxUdpPayloadSize; + } + + /** + * @return The IMS public user identifier or {@code null} if it was not set. + */ + public @Nullable String getPublicUserIdentifier() { + return mPublicUserIdentifier; + } + + /** + * @return The IMS private user identifier or {@code null} if it was not set. + */ + public @Nullable String getPrivateUserIdentifier() { + return mPrivateUserIdentifier; + } + + /** + * @return The IMS home domain or {@code null} if it was not set. + */ + public @Nullable String getHomeDomain() { + return mHomeDomain; + } + + /** + * get the IMEI of the associated device. + * <p> + * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the Contact + * header with a value of the device IMEI in the form {@code "urn:gsma:imei:<device IMEI>"}. + * @return The IMEI of the device or {@code null} if it was not set. + */ + public @Nullable String getImei() { + return mImei; + } + + /** + * @return The IPSec configuration that must be used because SIP is communicating over IPSec. + * This returns {@code null} SIP is not communicating over IPSec. + */ + public @Nullable IpSecConfiguration getIpSecConfiguration() { + return mIpSecConfiguration; + } + + /** + * @return The public IP address and port of the device due to it being behind a NAT. + * This returns {@code null} if the device is not behind a NAT. + */ + public @Nullable InetSocketAddress getNatSocketAddress() { + return mNatAddress; + } + + /** + * @return The device's Globally routable user-agent URI (GRUU) or {@code null} if this feature + * is not enabled for the SIP delegate. + */ + public @Nullable Uri getPublicGruuUri() { + return mGruu; + } + + /** + * @return The value of the SIP authentication header or {@code null} if there is none set. + */ + public @Nullable String getSipAuthenticationHeader() { + return mSipAuthHeader; + } + + /** + * @return The value of the SIP authentication nonce or {@code null} if there is none set. + */ + public @Nullable String getSipAuthenticationNonce() { + return mSipAuthNonce; + } + + /** + * @return The value of the SIP service route header or {@code null} if there is none set. + */ + public @Nullable String getSipServiceRouteHeader() { + return mServiceRouteHeader; + } + + /** + * @return The value of the SIP path header or {@code null} if there is none set. + */ + public @Nullable String getSipPathHeader() { + return mPathHeader; + } + + /** + * @return The value of the SIP User-Agent header or {@code null} if there is none set. + */ + public @Nullable String getSipUserAgentHeader() { + return mUserAgentHeader; + } + /** + * @return The value of the SIP Contact header's User parameter or {@code null} if there is + * none set. + */ + public @Nullable String getSipContactUserParameter() { + return mContactUserParam; + } + + /** + * @return The value of the SIP P-Access-Network-Info (P-ANI) header or {@code null} if there is + * none set. + */ + public @Nullable String getSipPaniHeader() { + return mPaniHeader; + } + /** + * @return The value of the SIP P-Last-Access-Network-Info (P-LANI) header or {@code null} if + * there is none set. + */ + public @Nullable String getSipPlaniHeader() { + return mPlaniHeader; + } + + /** + * @return The value of the SIP Cellular-Network-Info (CNI) header or {@code null} if there is + * none set. + */ + public @Nullable String getSipCniHeader() { + return mCniHeader; + } + + /** + * @return The value of the SIP P-associated-uri header or {@code null} if there is none set. + */ + public @Nullable String getSipAssociatedUriHeader() { + return mAssociatedUriHeader; + } + + private void writeAddressToParcel(InetSocketAddress addr, Parcel dest) { + dest.writeByteArray(addr.getAddress().getAddress()); + dest.writeInt(addr.getPort()); + } + + private InetSocketAddress readAddressFromParcel(Parcel source) { + final byte[] addressBytes = source.createByteArray(); + final int port = source.readInt(); + try { + return new InetSocketAddress(InetAddress.getByAddress(addressBytes), port); + } catch (UnknownHostException e) { + // Should not happen, as length of array was verified before parcelling. + Log.e("SipDelegateConfiguration", "exception reading address, returning null"); + return null; + } + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<SipDelegateConfiguration> CREATOR = + new Creator<SipDelegateConfiguration>() { + @Override + public SipDelegateConfiguration createFromParcel(Parcel source) { + return new SipDelegateConfiguration(source); + } + + @Override + public SipDelegateConfiguration[] newArray(int size) { + return new SipDelegateConfiguration[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SipDelegateConfiguration that = (SipDelegateConfiguration) o; + return mVersion == that.mVersion + && mTransportType == that.mTransportType + && mIsSipCompactFormEnabled == that.mIsSipCompactFormEnabled + && mIsSipKeepaliveEnabled == that.mIsSipKeepaliveEnabled + && mMaxUdpPayloadSize == that.mMaxUdpPayloadSize + && Objects.equals(mLocalAddress, that.mLocalAddress) + && Objects.equals(mSipServerAddress, that.mSipServerAddress) + && Objects.equals(mPublicUserIdentifier, that.mPublicUserIdentifier) + && Objects.equals(mPrivateUserIdentifier, that.mPrivateUserIdentifier) + && Objects.equals(mHomeDomain, that.mHomeDomain) + && Objects.equals(mImei, that.mImei) + && Objects.equals(mGruu, that.mGruu) + && Objects.equals(mSipAuthHeader, that.mSipAuthHeader) + && Objects.equals(mSipAuthNonce, that.mSipAuthNonce) + && Objects.equals(mServiceRouteHeader, that.mServiceRouteHeader) + && Objects.equals(mPathHeader, that.mPathHeader) + && Objects.equals(mUserAgentHeader, that.mUserAgentHeader) + && Objects.equals(mContactUserParam, that.mContactUserParam) + && Objects.equals(mPaniHeader, that.mPaniHeader) + && Objects.equals(mPlaniHeader, that.mPlaniHeader) + && Objects.equals(mCniHeader, that.mCniHeader) + && Objects.equals(mAssociatedUriHeader, that.mAssociatedUriHeader) + && Objects.equals(mIpSecConfiguration, that.mIpSecConfiguration) + && Objects.equals(mNatAddress, that.mNatAddress); + } + + @Override + public int hashCode() { + return Objects.hash(mVersion, mTransportType, mLocalAddress, mSipServerAddress, + mIsSipCompactFormEnabled, mIsSipKeepaliveEnabled, mMaxUdpPayloadSize, + mPublicUserIdentifier, mPrivateUserIdentifier, mHomeDomain, mImei, mGruu, + mSipAuthHeader, mSipAuthNonce, mServiceRouteHeader, mPathHeader, mUserAgentHeader, + mContactUserParam, mPaniHeader, mPlaniHeader, mCniHeader, mAssociatedUriHeader, + mIpSecConfiguration, mNatAddress); + } + + @Override + public String toString() { + return "SipDelegateConfiguration{ mVersion=" + mVersion + ", mTransportType=" + + mTransportType + '}'; + } +} diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java index d7a19bc0cb62..4dbb08d14ccd 100644 --- a/telephony/java/android/telephony/ims/SipDelegateConnection.java +++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java @@ -48,7 +48,7 @@ public interface SipDelegateConnection { * sending the message. * @param sipMessage The SipMessage to be sent. * @param configVersion The SipDelegateImsConfiguration version used to construct the - * SipMessage. See {@link SipDelegateImsConfiguration#getVersion} for more + * SipMessage. See {@link SipDelegateConfiguration#getVersion} for more */ void sendMessage(@NonNull SipMessage sipMessage, long configVersion); diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java index 0d63f7bba741..ffbfde65e2d3 100644 --- a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java +++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java @@ -21,35 +21,21 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.net.InetAddresses; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; -import android.telephony.ims.stub.SipDelegate; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.InetSocketAddress; /** - * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the - * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s. - * <p> - * The IMS service must generate new instances of this configuration as the IMS configuration - * managed by the IMS service changes. Along with each {@link SipDelegateImsConfiguration} instance - * containing the configuration is the "version", which should be incremented every time a new - * {@link SipDelegateImsConfiguration} instance is created. The {@link SipDelegateConnection} will - * include the version of the {@link SipDelegateImsConfiguration} instance that it used in order for - * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration - * to generate the {@link SipMessage} and return - * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in - * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can - * regenerate that {@link SipMessage} using the correct {@link SipDelegateImsConfiguration} - * instance. - * <p> - * Every time the IMS configuration state changes in the IMS service, a full configuration should - * be generated. The new {@link SipDelegateImsConfiguration} instance should not be an incremental - * update. * @hide + * @deprecated Use {@link SipDelegateConfiguration} instead. */ +@Deprecated @SystemApi public final class SipDelegateImsConfiguration implements Parcelable { @@ -535,4 +521,68 @@ public final class SipDelegateImsConfiguration implements Parcelable { return new SipDelegateImsConfiguration[size]; } }; + + /** + * Temporary helper to transition from old form of config to new form. + * @return new config + * @hide + */ + public SipDelegateConfiguration toNewConfig() { + // IP version is now included in call to InetSocketAddr + String transportTypeString = getString(KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING); + int transportType = (transportTypeString != null + && transportTypeString.equals(SIP_TRANSPORT_UDP)) + ? SipDelegateConfiguration.SIP_TRANSPORT_UDP + : SipDelegateConfiguration.SIP_TRANSPORT_TCP; + SipDelegateConfiguration.Builder builder = new SipDelegateConfiguration.Builder(mVersion, + transportType, + getSocketAddr(getString(KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING), + getInt(KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT, -1)), + getSocketAddr(getString(KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING), + getInt(KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT, -1))); + builder.setSipCompactFormEnabled( + getBoolean(KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL, false)); + builder.setSipKeepaliveEnabled( + getBoolean(KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL, false)); + builder.setMaxUdpPayloadSizeBytes(getInt(KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT, -1)); + builder.setPublicUserIdentifier(getString(KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING)); + builder.setPrivateUserIdentifier(getString(KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING)); + builder.setHomeDomain(getString(KEY_SIP_CONFIG_HOME_DOMAIN_STRING)); + builder.setImei(getString(KEY_SIP_CONFIG_IMEI_STRING)); + builder.setSipAuthenticationHeader(getString(KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING)); + builder.setSipAuthenticationNonce(getString(KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING)); + builder.setSipServiceRouteHeader(getString(KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING)); + builder.setSipPathHeader(getString(KEY_SIP_CONFIG_PATH_HEADER_STRING)); + builder.setSipUserAgentHeader(getString(KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING)); + builder.setSipContactUserParameter(getString(KEY_SIP_CONFIG_URI_USER_PART_STRING)); + builder.setSipPaniHeader(getString(KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING)); + builder.setSipPlaniHeader( + getString(KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING)); + builder.setSipCniHeader(getString(KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING)); + builder.setSipAssociatedUriHeader(getString(KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING)); + if (getBoolean(KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL, false)) { + builder.setPublicGruuUri(Uri.parse(getString(KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING))); + } + if (getBoolean(KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL, false)) { + builder.setIpSecConfiguration(new SipDelegateConfiguration.IpSecConfiguration( + getInt(KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT, -1), + getString(KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING)) + ); + } + if (getBoolean(KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL, false)) { + builder.setNatSocketAddress(getSocketAddr( + getString(KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING), + getInt(KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT, -1))); + } + return builder.build(); + } + + private InetSocketAddress getSocketAddr(String ipAddr, int port) { + return new InetSocketAddress(InetAddresses.parseNumericAddress(ipAddr), port); + } } diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java index f65afa52785d..ee7302a753cc 100644 --- a/telephony/java/android/telephony/ims/SipDelegateManager.java +++ b/telephony/java/android/telephony/ims/SipDelegateManager.java @@ -125,12 +125,12 @@ public class SipDelegateManager { public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9; /** - * The outgoing SIP message has not been sent because the {@link SipDelegateImsConfiguration} + * The outgoing SIP message has not been sent because the {@link SipDelegateConfiguration} * version associated with the outgoing {@link SipMessage} is now stale and has failed * validation checks. * <p> * The @link SipMessage} should be recreated using the newest - * {@link SipDelegateImsConfiguration} and sent again. + * {@link SipDelegateConfiguration} and sent again. */ public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10; diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl index ddfcb9994cb8..855000bb57fb 100644 --- a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl @@ -18,6 +18,7 @@ package android.telephony.ims.aidl; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.aidl.ISipDelegate; @@ -30,5 +31,6 @@ oneway interface ISipDelegateConnectionStateCallback { void onFeatureTagStatusChanged(in DelegateRegistrationState registrationState, in List<FeatureTagState> deniedFeatureTags); void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig); + void onConfigurationChanged(in SipDelegateConfiguration registeredSipConfig); void onDestroyed(int reason); } diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl index 609ee260cbab..4c3c93d36188 100644 --- a/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl @@ -18,6 +18,7 @@ package android.telephony.ims.aidl; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.aidl.ISipDelegate; @@ -29,5 +30,6 @@ oneway interface ISipDelegateStateCallback { void onCreated(ISipDelegate c, in List<FeatureTagState> deniedFeatureTags); void onFeatureTagRegistrationChanged(in DelegateRegistrationState registrationState); void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig); + void onConfigurationChanged(in SipDelegateConfiguration registeredSipConfig); void onDestroyed(int reason); } diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java index 6a98d80d6b9b..c18ab33eb2c9 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java @@ -24,6 +24,7 @@ import android.telephony.ims.DelegateMessageCallback; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.DelegateStateCallback; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; @@ -166,6 +167,15 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe } @Override + public void onConfigurationChanged(@NonNull SipDelegateConfiguration config) { + try { + mStateBinder.onConfigurationChanged(config); + } catch (RemoteException e) { + // BinderDied will trigger destroySipDelegate, so just ignore this locally. + } + } + + @Override public void onDestroyed(int reasonCode) { mDelegate = null; try { diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java index 0abb49574a73..47ddcb9696db 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java @@ -21,6 +21,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; @@ -90,6 +91,17 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } @Override + public void onConfigurationChanged(SipDelegateConfiguration registeredSipConfig) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mStateCallback.onConfigurationChanged(registeredSipConfig)); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override public void onDestroyed(int reason) { invalidateSipDelegateBinder(); final long token = Binder.clearCallingIdentity(); diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java index 02218ead0ad7..c078637e3791 100644 --- a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java +++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java @@ -21,6 +21,7 @@ import android.annotation.SystemApi; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.DelegateRequest; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; @@ -44,7 +45,7 @@ import java.util.Set; * <p> * In order to start sending SIP messages, the SIP configuration parameters will need to be * received, so the messaging application should make no assumptions about these parameters and wait - * until {@link #onImsConfigurationChanged(SipDelegateImsConfiguration)} has been called. This is + * until {@link #onConfigurationChanged(SipDelegateConfiguration)} has been called. This is * guaranteed to happen after the first {@link #onFeatureTagStatusChanged} if there is at least one * feature tag that has been successfully associated with the {@link SipDelegateConnection}. If all * feature tags were denied, no IMS configuration will be sent. @@ -135,8 +136,32 @@ public interface DelegateConnectionStateCallback { * not compleed yet. * * @param registeredSipConfig The configuration of the IMS stack registered on the IMS network. + * @deprecated Will not be in final API, use + * {@link #onConfigurationChanged(SipDelegateConfiguration)} instead}. */ - void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration registeredSipConfig); + @Deprecated + default void onImsConfigurationChanged( + @NonNull SipDelegateImsConfiguration registeredSipConfig) { + onConfigurationChanged(registeredSipConfig.toNewConfig()); + } + + /** + * IMS configuration of the underlying IMS stack used by this IMS application for construction + * of the SIP messages that will be sent over the carrier's network. + * <p> + * There should never be assumptions made about the configuration of the underling IMS stack and + * the IMS application should wait for this indication before sending out any outgoing SIP + * messages. + * <p> + * Configuration may change due to IMS registration changes as well as + * other optional events on the carrier network. If IMS stack is already registered at the time + * of callback registration, then this method shall be invoked with the current configuration. + * Otherwise, there may be a delay in this method being called if initial IMS registration has + * not compleed yet. + * + * @param registeredSipConfig The configuration of the IMS stack registered on the IMS network. + */ + default void onConfigurationChanged(@NonNull SipDelegateConfiguration registeredSipConfig) {} /** * The previously created {@link SipDelegateConnection} instance delivered via diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java index d5198a0aa25c..997d00bc91c7 100644 --- a/telephony/java/android/telephony/ims/stub/SipDelegate.java +++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java @@ -21,8 +21,8 @@ import android.annotation.SystemApi; import android.telephony.ims.DelegateMessageCallback; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.ImsService; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; -import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; @@ -38,7 +38,7 @@ import android.telephony.ims.SipMessage; * modified to include the features managed by these SipDelegates. * <p> * This SipDelegate will need to notify the remote application of the registration of these features - * as well as the associated {@link SipDelegateImsConfiguration} before the application can start + * as well as the associated {@link SipDelegateConfiguration} before the application can start * sending/receiving SIP messages via the transport. See * {@link android.telephony.ims.DelegateStateCallback} for more information. * @hide @@ -55,9 +55,9 @@ public interface SipDelegate { * {@link DelegateMessageCallback#onMessageSendFailure(String, int)}. * @param message The SIP message to be sent over the operator’s network. * @param configVersion The SipDelegateImsConfiguration version used to construct the - * SipMessage. See {@link SipDelegateImsConfiguration} for more information. If the + * SipMessage. See {@link SipDelegateConfiguration} for more information. If the * version specified here does not match the most recently constructed - * {@link SipDelegateImsConfiguration}, this message should fail validation checks and + * {@link SipDelegateConfiguration}, this message should fail validation checks and * {@link DelegateMessageCallback#onMessageSendFailure} should be called with code * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION}. */ |