933 lines
36 KiB
Java
933 lines
36 KiB
Java
![]() |
/*
|
||
|
* 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, android.net.Uri.class);
|
||
|
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 + '}';
|
||
|
}
|
||
|
}
|