1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telephony.ims;
18 
19 import android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.net.InetAddresses;
25 import android.net.Uri;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.telephony.ims.stub.SipDelegate;
29 import android.util.Log;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.net.InetAddress;
34 import java.net.InetSocketAddress;
35 import java.net.UnknownHostException;
36 import java.util.Objects;
37 
38 /**
39  * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the
40  * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s.
41  * <p>
42  * The IMS service must generate new instances of this configuration as the IMS configuration
43  * managed by the IMS service changes. Along with each {@link SipDelegateConfiguration} instance
44  * containing the configuration is the "version", which should be incremented every time a new
45  * {@link SipDelegateConfiguration} instance is created. The {@link SipDelegateConnection} will
46  * include the version of the {@link SipDelegateConfiguration} instance that it used in order for
47  * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration
48  * to generate the {@link SipMessage} and return
49  * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in
50  * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can
51  * regenerate that {@link SipMessage} using the correct {@link SipDelegateConfiguration}
52  * instance.
53  * <p>
54  * Every time the IMS configuration state changes in the IMS service, a full configuration should
55  * be generated. The new  {@link SipDelegateConfiguration} instance should not be an incremental
56  * update.
57  * @see Builder
58  * @hide
59  */
60 @SystemApi
61 public final class SipDelegateConfiguration implements Parcelable {
62 
63     /**
64      * The SIP transport uses UDP.
65      */
66     public static final int SIP_TRANSPORT_UDP = 0;
67 
68     /**
69      * The SIP transport uses TCP.
70      */
71     public static final int SIP_TRANSPORT_TCP = 1;
72 
73     /**@hide*/
74     @IntDef(prefix = "SIP_TRANSPORT_", value = {
75             SIP_TRANSPORT_UDP,
76             SIP_TRANSPORT_TCP
77     })
78     @Retention(RetentionPolicy.SOURCE)
79     public @interface TransportType {}
80 
81     /**
82      * The value returned by {@link #getMaxUdpPayloadSizeBytes()} when it is not defined.
83      */
84     public static final int UDP_PAYLOAD_SIZE_UNDEFINED = -1;
85 
86     /**
87      * SIP over IPSec configuration
88      */
89     public static final class IpSecConfiguration {
90         private final int mLocalTxPort;
91         private final int mLocalRxPort;
92         private final int mLastLocalTxPort;
93         private final int mRemoteTxPort;
94         private final int mRemoteRxPort;
95         private final int mLastRemoteTxPort;
96         private final String mSecurityHeader;
97 
98         /**
99          * Describes the SIP over IPSec configuration the SipDelegate will need to use.
100          *
101          * @param localTxPort  Local SIP port number used to send traffic.
102          * @param localRxPort Local SIP port number used to receive traffic.
103          * @param lastLocalTxPort Local SIP port number used for the previous IPsec security
104          *                        association.
105          * @param remoteTxPort Remote port number used by the SIP server to send SIP traffic.
106          * @param remoteRxPort Remote port number used by the SIP server to receive incoming SIP
107          *                     traffic.
108          * @param lastRemoteTxPort Remote port number used by the SIP server to send SIP traffic on
109          *                         the previous IPSec security association.
110          * @param securityHeader The value of the SIP security verify header.
111          */
IpSecConfiguration(int localTxPort, int localRxPort, int lastLocalTxPort, int remoteTxPort, int remoteRxPort, int lastRemoteTxPort, @NonNull String securityHeader)112         public IpSecConfiguration(int localTxPort, int localRxPort, int lastLocalTxPort,
113                 int remoteTxPort, int remoteRxPort, int lastRemoteTxPort,
114                 @NonNull String securityHeader) {
115             mLocalTxPort = localTxPort;
116             mLocalRxPort = localRxPort;
117             mLastLocalTxPort = lastLocalTxPort;
118             mRemoteTxPort = remoteTxPort;
119             mRemoteRxPort = remoteRxPort;
120             mLastRemoteTxPort = lastRemoteTxPort;
121             mSecurityHeader = securityHeader;
122         }
123 
124         /**
125          * @return The local SIP port number used to send traffic.
126          */
getLocalTxPort()127         public int getLocalTxPort() {
128             return mLocalTxPort;
129         }
130 
131         /**
132          * @return The Local SIP port number used to receive traffic.
133          */
getLocalRxPort()134         public int getLocalRxPort() {
135             return mLocalRxPort;
136         }
137 
138         /**
139          * @return The last local SIP port number used for the previous IPsec security association.
140          */
getLastLocalTxPort()141         public int getLastLocalTxPort() {
142             return mLastLocalTxPort;
143         }
144 
145         /**
146          * @return The remote port number used by the SIP server to send SIP traffic.
147          */
getRemoteTxPort()148         public int getRemoteTxPort() {
149             return mRemoteTxPort;
150         }
151 
152         /**
153          * @return the remote port number used by the SIP server to receive incoming SIP traffic.
154          */
getRemoteRxPort()155         public int getRemoteRxPort() {
156             return mRemoteRxPort;
157         }
158 
159         /**
160          * @return the remote port number used by the SIP server to send SIP traffic on the previous
161          * IPSec security association.
162          */
getLastRemoteTxPort()163         public int getLastRemoteTxPort() {
164             return mLastRemoteTxPort;
165         }
166 
167         /**
168          * @return The value of the SIP security verify header.
169          */
getSipSecurityVerifyHeader()170         public @NonNull String getSipSecurityVerifyHeader() {
171             return mSecurityHeader;
172         }
173 
174         /**
175          * Helper for parcelling this object.
176          * @hide
177          */
addToParcel(Parcel dest)178         public void addToParcel(Parcel dest) {
179             dest.writeInt(mLocalTxPort);
180             dest.writeInt(mLocalRxPort);
181             dest.writeInt(mLastLocalTxPort);
182             dest.writeInt(mRemoteTxPort);
183             dest.writeInt(mRemoteRxPort);
184             dest.writeInt(mLastRemoteTxPort);
185             dest.writeString(mSecurityHeader);
186         }
187 
188         /**
189          * Helper for unparcelling this object.
190          * @hide
191          */
fromParcel(Parcel source)192         public static IpSecConfiguration fromParcel(Parcel source) {
193             return new IpSecConfiguration(source.readInt(), source.readInt(), source.readInt(),
194                     source.readInt(), source.readInt(), source.readInt(), source.readString());
195         }
196 
197         @Override
toString()198         public String toString() {
199             return "IpSecConfiguration{" + "localTx=" + mLocalTxPort + ", localRx=" + mLocalRxPort
200                     + ", lastLocalTx=" + mLastLocalTxPort + ", remoteTx=" + mRemoteTxPort
201                     + ", remoteRx=" + mRemoteRxPort + ", lastRemoteTx=" + mLastRemoteTxPort
202                     + ", securityHeader=" + mSecurityHeader + '}';
203         }
204 
205         @Override
equals(Object o)206         public boolean equals(Object o) {
207             if (this == o) return true;
208             if (o == null || getClass() != o.getClass()) return false;
209             IpSecConfiguration that = (IpSecConfiguration) o;
210             return mLocalTxPort == that.mLocalTxPort
211                     && mLocalRxPort == that.mLocalRxPort
212                     && mLastLocalTxPort == that.mLastLocalTxPort
213                     && mRemoteTxPort == that.mRemoteTxPort
214                     && mRemoteRxPort == that.mRemoteRxPort
215                     && mLastRemoteTxPort == that.mLastRemoteTxPort
216                     && Objects.equals(mSecurityHeader, that.mSecurityHeader);
217         }
218 
219         @Override
hashCode()220         public int hashCode() {
221             return Objects.hash(mLocalTxPort, mLocalRxPort, mLastLocalTxPort, mRemoteTxPort,
222                     mRemoteRxPort, mLastRemoteTxPort, mSecurityHeader);
223         }
224     }
225 
226     /**
227      *  Creates a new instance of {@link SipDelegateConfiguration} composed from optional
228      *  configuration items.
229      */
230     public static final class Builder {
231         private final SipDelegateConfiguration mConfig;
232 
233         /**
234          *
235          * @param version The version associated with the {@link SipDelegateConfiguration} instance
236          *                being built. See {@link #getVersion()} for more information.
237          * @param transportType The transport type to use for SIP signalling.
238          * @param localAddr The local socket address used for SIP traffic.
239          * @param serverAddr The SIP server or P-CSCF default IP address for sip traffic.
240          * @see InetAddresses#parseNumericAddress(String) for how to create an
241          * {@link InetAddress} without requiring a DNS lookup.
242          */
Builder(@ntRangefrom = 0) long version, @TransportType int transportType, @NonNull InetSocketAddress localAddr, @NonNull InetSocketAddress serverAddr)243         public Builder(@IntRange(from = 0) long version, @TransportType int transportType,
244                 @NonNull InetSocketAddress localAddr, @NonNull InetSocketAddress serverAddr) {
245             mConfig = new SipDelegateConfiguration(version, transportType, localAddr,
246                     serverAddr);
247         }
248 
249         /**
250          * Create a new {@link SipDelegateConfiguration} instance with the same exact configuration
251          * as the passed in instance, except for the version parameter, which will be incremented
252          * by 1.
253          * <p>
254          * This method is useful for cases where only a small subset of configurations have changed
255          * and the new configuration is based off of the old configuration.
256          * @param c The older {@link SipDelegateConfiguration} instance to base this instance's
257          *          configuration off of.
258          */
Builder(@onNull SipDelegateConfiguration c)259         public Builder(@NonNull SipDelegateConfiguration c) {
260             mConfig = c.copyAndIncrementVersion();
261         }
262 
263         /**
264          * Sets whether or not SIP compact form is enabled for the associated SIP delegate.
265          * <p>
266          * If unset, this configuration defaults to {@code false}.
267          * @param isEnabled {@code true} if SIP compact form is enabled for the associated SIP
268          *     Delegate, {@code false} if it is not.
269          * @return this Builder instance with the compact form configuration set.
270          */
setSipCompactFormEnabled(boolean isEnabled)271         public @NonNull Builder setSipCompactFormEnabled(boolean isEnabled) {
272             mConfig.mIsSipCompactFormEnabled = isEnabled;
273             return this;
274         }
275 
276         /**
277          * Sets whether or not underlying SIP keepalives are enabled for the associated SIP
278          * delegate.
279          * <p>
280          * If unset, this configuration defaults to {@code false}.
281          * @param isEnabled {@code true} if SIP keepalives are enabled for the associated SIP
282          *     Delegate, {@code false} if it is not.
283          * @return this Builder instance with the new configuration set.
284          */
setSipKeepaliveEnabled(boolean isEnabled)285         public @NonNull Builder setSipKeepaliveEnabled(boolean isEnabled) {
286             mConfig.mIsSipKeepaliveEnabled = isEnabled;
287             return this;
288         }
289 
290         /**
291          * Sets the max SIP payload size in bytes to be sent on UDP. If the SIP message payload is
292          * greater than the max UDP payload size, then TCP must be used.
293          * <p>
294          * If unset, this configuration defaults to {@link #UDP_PAYLOAD_SIZE_UNDEFINED}, or no
295          * size specified.
296          * @param size The maximum SIP payload size in bytes for UDP.
297          * @return this Builder instance with the new configuration set.
298          */
setMaxUdpPayloadSizeBytes(@ntRangefrom = 1) int size)299         public @NonNull Builder setMaxUdpPayloadSizeBytes(@IntRange(from = 1) int size) {
300             mConfig.mMaxUdpPayloadSize = size;
301             return this;
302         }
303 
304         /**
305          * Sets the IMS public user identifier.
306          * <p>
307          * If unset, this configuration defaults to {@code null}, or no identifier specified.
308          * @param id The IMS public user identifier.
309          * @return this Builder instance with the new configuration set.
310          */
setPublicUserIdentifier(@ullable String id)311         public @NonNull Builder setPublicUserIdentifier(@Nullable String id) {
312             mConfig.mPublicUserIdentifier = id;
313             return this;
314         }
315 
316         /**
317          * Sets the IMS private user identifier.
318          * <p>
319          * If unset, this configuration defaults to {@code null}, or no identifier specified.
320          * @param id The IMS private user identifier.
321          * @return this Builder instance with the new configuration set.
322          */
setPrivateUserIdentifier(@ullable String id)323         public @NonNull Builder setPrivateUserIdentifier(@Nullable String id) {
324             mConfig.mPrivateUserIdentifier = id;
325             return this;
326         }
327 
328         /**
329          * Sets the IMS home domain.
330          * <p>
331          * If unset, this configuration defaults to {@code null}, or no domain specified.
332          * @param domain The IMS home domain.
333          * @return this Builder instance with the new configuration set.
334          */
setHomeDomain(@ullable String domain)335         public @NonNull Builder setHomeDomain(@Nullable String domain) {
336             mConfig.mHomeDomain = domain;
337             return this;
338         }
339 
340         /**
341          * Sets the IMEI of the associated device.
342          * <p>
343          * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the
344          * Contact header with a value of the device IMEI in the form
345          * {@code "urn:gsma:imei:<device IMEI>"}.
346          * <p>
347          * If unset, this configuration defaults to {@code null}, or no IMEI string specified.
348          * @param imei The IMEI of the device.
349          * @return this Builder instance with the new configuration set.
350          */
setImei(@ullable String imei)351         public @NonNull Builder setImei(@Nullable String imei) {
352             mConfig.mImei = imei;
353             return this;
354         }
355 
356         /**
357          * Set the optional {@link IpSecConfiguration} instance used if the associated SipDelegate
358          * is communicating over IPSec.
359          * <p>
360          * If unset, this configuration defaults to {@code null}
361          * @param c The IpSecConfiguration instance to set.
362          * @return this Builder instance with IPSec configuration set.
363          */
setIpSecConfiguration(@ullable IpSecConfiguration c)364         public @NonNull Builder setIpSecConfiguration(@Nullable IpSecConfiguration c) {
365             mConfig.mIpSecConfiguration = c;
366             return this;
367         }
368 
369         /**
370          * Describes the Device's Public IP Address and port that is set when Network Address
371          * Translation is enabled and the device is behind a NAT.
372          * <p>
373          * If unset, this configuration defaults to {@code null}
374          * @param addr The {@link InetAddress} representing the device's public IP address and port
375          *          when behind a NAT.
376          * @return this Builder instance with the new configuration set.
377          * @see InetAddresses#parseNumericAddress(String) For an example of how to create an
378          * instance of {@link InetAddress} without causing a DNS lookup.
379          */
setNatSocketAddress(@ullable InetSocketAddress addr)380         public @NonNull Builder setNatSocketAddress(@Nullable InetSocketAddress addr) {
381             mConfig.mNatAddress = addr;
382             return this;
383         }
384 
385         /**
386          * Sets the optional URI of the device's Globally routable user-agent URI (GRUU) if this
387          * feature is enabled for the SIP delegate.
388          * <p>
389          * If unset, this configuration defaults to {@code null}
390          * @param uri The GRUU to set.
391          * @return this builder instance with the new configuration set.
392          */
setPublicGruuUri(@ullable Uri uri)393         public @NonNull Builder setPublicGruuUri(@Nullable Uri uri) {
394             mConfig.mGruu = uri;
395             return this;
396         }
397 
398         /**
399          * Sets the SIP authentication header value.
400          * <p>
401          * If unset, this configuration defaults to {@code null}.
402          * @param header The SIP authentication header's value.
403          * @return this builder instance with the new configuration set.
404          */
setSipAuthenticationHeader(@ullable String header)405         public @NonNull Builder setSipAuthenticationHeader(@Nullable String header) {
406             mConfig.mSipAuthHeader = header;
407             return this;
408         }
409 
410         /**
411          * Sets the SIP authentication nonce.
412          * <p>
413          * If unset, this configuration defaults to {@code null}.
414          * @param nonce The SIP authentication nonce.
415          * @return this builder instance with the new configuration set.
416          */
setSipAuthenticationNonce(@ullable String nonce)417         public @NonNull Builder setSipAuthenticationNonce(@Nullable String nonce) {
418             mConfig.mSipAuthNonce = nonce;
419             return this;
420         }
421 
422         /**
423          * Sets the SIP service route header value.
424          * <p>
425          * If unset, this configuration defaults to {@code null}.
426          * @param header The SIP service route header value.
427          * @return this builder instance with the new configuration set.
428          */
setSipServiceRouteHeader(@ullable String header)429         public @NonNull Builder setSipServiceRouteHeader(@Nullable String header) {
430             mConfig.mServiceRouteHeader = header;
431             return this;
432         }
433 
434         /**
435          * Sets the SIP path header value.
436          * <p>
437          * If unset, this configuration defaults to {@code null}.
438          * @param header The SIP path header value.
439          * @return this builder instance with the new configuration set.
440          */
setSipPathHeader(@ullable String header)441         public @NonNull Builder setSipPathHeader(@Nullable String header) {
442             mConfig.mPathHeader = header;
443             return this;
444         }
445 
446         /**
447          * Sets the SIP User-Agent header value.
448          * <p>
449          * If unset, this configuration defaults to {@code null}.
450          * @param header The SIP User-Agent header value.
451          * @return this builder instance with the new configuration set.
452          */
setSipUserAgentHeader(@ullable String header)453         public @NonNull Builder setSipUserAgentHeader(@Nullable String header) {
454             mConfig.mUserAgentHeader = header;
455             return this;
456         }
457 
458         /**
459          * Sets the SIP Contact header's User parameter value.
460          * <p>
461          * If unset, this configuration defaults to {@code null}.
462          * @param param The SIP Contact header's User parameter value.
463          * @return this builder instance with the new configuration set.
464          */
setSipContactUserParameter(@ullable String param)465         public @NonNull Builder setSipContactUserParameter(@Nullable String param) {
466             mConfig.mContactUserParam = param;
467             return this;
468         }
469 
470         /**
471          * Sets the SIP P-Access-Network-Info (P-ANI) header value. Populated for networks that
472          * require this information to be provided as part of outgoing SIP messages.
473          * <p>
474          * If unset, this configuration defaults to {@code null}.
475          * @param header The SIP P-ANI header value.
476          * @return this builder instance with the new configuration set.
477          */
setSipPaniHeader(@ullable String header)478         public @NonNull Builder setSipPaniHeader(@Nullable String header) {
479             mConfig.mPaniHeader = header;
480             return this;
481         }
482 
483         /**
484          * Sets the SIP P-Last-Access-Network-Info (P-LANI) header value. Populated for
485          * networks that require this information to be provided as part of outgoing SIP messages.
486          * <p>
487          * If unset, this configuration defaults to {@code null}.
488          * @param header The SIP P-LANI header value.
489          * @return this builder instance with the new configuration set.
490          */
setSipPlaniHeader(@ullable String header)491         public @NonNull Builder setSipPlaniHeader(@Nullable String header) {
492             mConfig.mPlaniHeader = header;
493             return this;
494         }
495 
496         /**
497          * Sets the SIP Cellular-Network-Info (CNI) header value (See 3GPP 24.229, section 7.2.15),
498          * populated for networks that require this information to be provided as part of outgoing
499          * SIP messages.
500          * <p>
501          * If unset, this configuration defaults to {@code null}.
502          * @param header The SIP P-LANI header value.
503          * @return this builder instance with the new configuration set.
504          */
setSipCniHeader(@ullable String header)505         public @NonNull Builder setSipCniHeader(@Nullable String header) {
506             mConfig.mCniHeader = header;
507             return this;
508         }
509 
510         /**
511          * Sets the SIP P-associated-uri header value.
512          * <p>
513          * If unset, this configuration defaults to {@code null}.
514          * @param header The SIP P-associated-uri header value.
515          * @return this builder instance with the new configuration set.
516          */
setSipAssociatedUriHeader(@ullable String header)517         public @NonNull Builder setSipAssociatedUriHeader(@Nullable String header) {
518             mConfig.mAssociatedUriHeader = header;
519             return this;
520         }
521 
522         /**
523          * @return A {@link SipDelegateConfiguration} instance with the optional configurations set.
524          */
build()525         public @NonNull SipDelegateConfiguration build() {
526             return mConfig;
527         }
528     }
529 
530     private final long mVersion;
531     private final int mTransportType;
532     private final InetSocketAddress mLocalAddress;
533     private final InetSocketAddress mSipServerAddress;
534     private boolean mIsSipCompactFormEnabled = false;
535     private boolean mIsSipKeepaliveEnabled = false;
536     private int mMaxUdpPayloadSize = -1;
537     private String mPublicUserIdentifier = null;
538     private String mPrivateUserIdentifier = null;
539     private String mHomeDomain = null;
540     private String mImei = null;
541     private Uri mGruu = null;
542     private String mSipAuthHeader = null;
543     private String mSipAuthNonce = null;
544     private String mServiceRouteHeader = null;
545     private String mPathHeader = null;
546     private String mUserAgentHeader = null;
547     private String mContactUserParam = null;
548     private String mPaniHeader = null;
549     private String mPlaniHeader = null;
550     private String mCniHeader = null;
551     private String mAssociatedUriHeader = null;
552     private IpSecConfiguration mIpSecConfiguration = null;
553     private InetSocketAddress mNatAddress = null;
554 
555 
SipDelegateConfiguration(long version, int transportType, InetSocketAddress localAddress, InetSocketAddress sipServerAddress)556     private SipDelegateConfiguration(long version, int transportType,
557             InetSocketAddress localAddress, InetSocketAddress sipServerAddress) {
558         mVersion = version;
559         mTransportType = transportType;
560         mLocalAddress = localAddress;
561         mSipServerAddress = sipServerAddress;
562     }
563 
SipDelegateConfiguration(Parcel source)564     private SipDelegateConfiguration(Parcel source) {
565         mVersion = source.readLong();
566         mTransportType = source.readInt();
567         mLocalAddress = readAddressFromParcel(source);
568         mSipServerAddress = readAddressFromParcel(source);
569         mIsSipCompactFormEnabled = source.readBoolean();
570         mIsSipKeepaliveEnabled = source.readBoolean();
571         mMaxUdpPayloadSize = source.readInt();
572         mPublicUserIdentifier = source.readString();
573         mPrivateUserIdentifier = source.readString();
574         mHomeDomain = source.readString();
575         mImei = source.readString();
576         mGruu = source.readParcelable(null);
577         mSipAuthHeader = source.readString();
578         mSipAuthNonce = source.readString();
579         mServiceRouteHeader = source.readString();
580         mPathHeader = source.readString();
581         mUserAgentHeader = source.readString();
582         mContactUserParam = source.readString();
583         mPaniHeader = source.readString();
584         mPlaniHeader = source.readString();
585         mCniHeader = source.readString();
586         mAssociatedUriHeader = source.readString();
587         boolean isIpsecConfigAvailable = source.readBoolean();
588         if (isIpsecConfigAvailable) {
589             mIpSecConfiguration = IpSecConfiguration.fromParcel(source);
590         }
591         boolean isNatConfigAvailable = source.readBoolean();
592         if (isNatConfigAvailable) {
593             mNatAddress = readAddressFromParcel(source);
594         }
595     }
596 
597     @Override
writeToParcel(@onNull Parcel dest, int flags)598     public void writeToParcel(@NonNull Parcel dest, int flags) {
599         dest.writeLong(mVersion);
600         dest.writeInt(mTransportType);
601         writeAddressToParcel(mLocalAddress, dest);
602         writeAddressToParcel(mSipServerAddress, dest);
603         dest.writeBoolean(mIsSipCompactFormEnabled);
604         dest.writeBoolean(mIsSipKeepaliveEnabled);
605         dest.writeInt(mMaxUdpPayloadSize);
606         dest.writeString(mPublicUserIdentifier);
607         dest.writeString(mPrivateUserIdentifier);
608         dest.writeString(mHomeDomain);
609         dest.writeString(mImei);
610         dest.writeParcelable(mGruu, flags);
611         dest.writeString(mSipAuthHeader);
612         dest.writeString(mSipAuthNonce);
613         dest.writeString(mServiceRouteHeader);
614         dest.writeString(mPathHeader);
615         dest.writeString(mUserAgentHeader);
616         dest.writeString(mContactUserParam);
617         dest.writeString(mPaniHeader);
618         dest.writeString(mPlaniHeader);
619         dest.writeString(mCniHeader);
620         dest.writeString(mAssociatedUriHeader);
621         dest.writeBoolean(mIpSecConfiguration != null);
622         if (mIpSecConfiguration != null) {
623             mIpSecConfiguration.addToParcel(dest);
624         }
625         dest.writeBoolean(mNatAddress != null);
626         if (mNatAddress != null) {
627             writeAddressToParcel(mNatAddress, dest);
628         }
629     }
630 
631     /**
632      * @return A copy of this instance with an incremented version.
633      * @hide
634      */
copyAndIncrementVersion()635     public SipDelegateConfiguration copyAndIncrementVersion() {
636         SipDelegateConfiguration c = new SipDelegateConfiguration(getVersion() + 1, mTransportType,
637                 mLocalAddress, mSipServerAddress);
638         c.mIsSipCompactFormEnabled = mIsSipCompactFormEnabled;
639         c.mIsSipKeepaliveEnabled = mIsSipKeepaliveEnabled;
640         c.mMaxUdpPayloadSize = mMaxUdpPayloadSize;
641         c.mIpSecConfiguration = mIpSecConfiguration;
642         c.mNatAddress = mNatAddress;
643         c.mPublicUserIdentifier = mPublicUserIdentifier;
644         c.mPrivateUserIdentifier = mPrivateUserIdentifier;
645         c.mHomeDomain = mHomeDomain;
646         c.mImei = mImei;
647         c.mGruu = mGruu;
648         c.mSipAuthHeader = mSipAuthHeader;
649         c.mSipAuthNonce = mSipAuthNonce;
650         c.mServiceRouteHeader = mServiceRouteHeader;
651         c.mPathHeader = mPathHeader;
652         c.mUserAgentHeader = mUserAgentHeader;
653         c.mContactUserParam = mContactUserParam;
654         c.mPaniHeader = mPaniHeader;
655         c.mPlaniHeader = mPlaniHeader;
656         c.mCniHeader = mCniHeader;
657         c.mAssociatedUriHeader = mAssociatedUriHeader;
658         return c;
659     }
660 
661     /**
662      * An integer representing the version number of this SipDelegateImsConfiguration.
663      * {@link SipMessage}s that are created using this configuration will also have a this
664      * version number associated with them, which will allow the IMS service to validate that the
665      * {@link SipMessage} was using the latest configuration during creation and not a stale
666      * configuration due to race conditions between the configuration being updated and the RCS
667      * application not receiving the updated configuration before generating a new message.
668      * <p>
669      * The version number should be a positive number that starts at 0 and increments sequentially
670      * as new {@link SipDelegateConfiguration} instances are created to update the IMS
671      * configuration state.
672      *
673      * @return the version number associated with this {@link SipDelegateConfiguration}.
674      */
getVersion()675     public @IntRange(from = 0) long getVersion() {
676         return mVersion;
677     }
678 
679     /**
680      * @return The Transport type of the SIP delegate.
681      */
getTransportType()682     public @TransportType int getTransportType() {
683         return mTransportType;
684     }
685 
686     /**
687      * @return The local IP address and port used for SIP traffic.
688      */
getLocalAddress()689     public @NonNull InetSocketAddress getLocalAddress() {
690         return mLocalAddress;
691     }
692 
693     /**
694      * @return The default IP Address and port of the SIP server or P-CSCF used for SIP traffic.
695      */
getSipServerAddress()696     public @NonNull InetSocketAddress getSipServerAddress() {
697         return mSipServerAddress;
698     }
699 
700     /**
701      * @return {@code true} if SIP compact form is enabled for the associated SIP Delegate,
702      * {@code false} if it is not.
703      */
isSipCompactFormEnabled()704     public boolean isSipCompactFormEnabled() {
705         return mIsSipCompactFormEnabled;
706     }
707 
708     /**
709      * @return {@code true} if SIP keepalives are enabled for the associated SIP Delegate,
710      * {@code false} if it is not.
711      */
isSipKeepaliveEnabled()712     public boolean isSipKeepaliveEnabled() {
713         return mIsSipKeepaliveEnabled;
714     }
715 
716     /**
717      * @return The maximum SIP payload size in bytes for UDP or {code -1} if no value was set.
718      */
getMaxUdpPayloadSizeBytes()719     public int getMaxUdpPayloadSizeBytes() {
720         return mMaxUdpPayloadSize;
721     }
722 
723     /**
724      * @return The IMS public user identifier or {@code null} if it was not set.
725      */
getPublicUserIdentifier()726     public @Nullable String getPublicUserIdentifier() {
727         return mPublicUserIdentifier;
728     }
729 
730     /**
731      * @return The IMS private user identifier or {@code null} if it was not set.
732      */
getPrivateUserIdentifier()733     public @Nullable String getPrivateUserIdentifier() {
734         return mPrivateUserIdentifier;
735     }
736 
737     /**
738      * @return The IMS home domain or {@code null} if it was not set.
739      */
getHomeDomain()740     public @Nullable String getHomeDomain() {
741         return mHomeDomain;
742     }
743 
744     /**
745      * get the IMEI of the associated device.
746      * <p>
747      * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the Contact
748      * header with a value of the device IMEI in the form {@code "urn:gsma:imei:<device IMEI>"}.
749      * @return The IMEI of the device or {@code null} if it was not set.
750      */
getImei()751     public @Nullable String getImei() {
752         return mImei;
753     }
754 
755     /**
756      * @return The IPSec configuration that must be used because SIP is communicating over IPSec.
757      * This returns {@code null} SIP is not communicating over IPSec.
758      */
getIpSecConfiguration()759     public @Nullable IpSecConfiguration getIpSecConfiguration() {
760         return mIpSecConfiguration;
761     }
762 
763     /**
764      * @return The public IP address and port of the device due to it being behind a NAT.
765      * This returns {@code null} if the device is not behind a NAT.
766      */
getNatSocketAddress()767     public @Nullable InetSocketAddress getNatSocketAddress() {
768         return mNatAddress;
769     }
770 
771     /**
772      * @return The device's Globally routable user-agent URI (GRUU) or {@code null} if this feature
773      * is not enabled for the SIP delegate.
774      */
getPublicGruuUri()775     public @Nullable Uri getPublicGruuUri() {
776         return mGruu;
777     }
778 
779     /**
780      * @return The value of the SIP authentication header or {@code null} if there is none set.
781      */
getSipAuthenticationHeader()782     public @Nullable String getSipAuthenticationHeader() {
783         return mSipAuthHeader;
784     }
785 
786     /**
787      * @return The value of the SIP authentication nonce or {@code null} if there is none set.
788      */
getSipAuthenticationNonce()789     public @Nullable String getSipAuthenticationNonce() {
790         return mSipAuthNonce;
791     }
792 
793     /**
794      * @return The value of the SIP service route header or {@code null} if there is none set.
795      */
getSipServiceRouteHeader()796     public @Nullable String getSipServiceRouteHeader() {
797         return mServiceRouteHeader;
798     }
799 
800     /**
801      * @return The value of the SIP path header or {@code null} if there is none set.
802      */
getSipPathHeader()803     public @Nullable String getSipPathHeader() {
804         return mPathHeader;
805     }
806 
807     /**
808      * @return The value of the SIP User-Agent header or {@code null} if there is none set.
809      */
getSipUserAgentHeader()810     public @Nullable String getSipUserAgentHeader() {
811         return mUserAgentHeader;
812     }
813     /**
814      * @return The value of the SIP Contact header's User parameter or {@code null} if there is
815      * none set.
816      */
getSipContactUserParameter()817     public @Nullable String getSipContactUserParameter() {
818         return mContactUserParam;
819     }
820 
821     /**
822      * @return The value of the SIP P-Access-Network-Info (P-ANI) header or {@code null} if there is
823      * none set.
824      */
getSipPaniHeader()825     public @Nullable String getSipPaniHeader() {
826         return mPaniHeader;
827     }
828     /**
829      * @return The value of the SIP P-Last-Access-Network-Info (P-LANI) header or {@code null} if
830      * there is none set.
831      */
getSipPlaniHeader()832     public @Nullable String getSipPlaniHeader() {
833         return mPlaniHeader;
834     }
835 
836     /**
837      * @return The value of the SIP Cellular-Network-Info (CNI) header or {@code null} if there is
838      * none set.
839      */
getSipCniHeader()840     public @Nullable String getSipCniHeader() {
841         return mCniHeader;
842     }
843 
844     /**
845      * @return The value of the SIP P-associated-uri header or {@code null} if there is none set.
846      */
getSipAssociatedUriHeader()847     public @Nullable String getSipAssociatedUriHeader() {
848         return mAssociatedUriHeader;
849     }
850 
writeAddressToParcel(InetSocketAddress addr, Parcel dest)851     private void writeAddressToParcel(InetSocketAddress addr, Parcel dest) {
852         dest.writeByteArray(addr.getAddress().getAddress());
853         dest.writeInt(addr.getPort());
854     }
855 
readAddressFromParcel(Parcel source)856     private InetSocketAddress readAddressFromParcel(Parcel source) {
857         final byte[] addressBytes = source.createByteArray();
858         final int port = source.readInt();
859         try {
860             return new InetSocketAddress(InetAddress.getByAddress(addressBytes), port);
861         } catch (UnknownHostException e) {
862             // Should not happen, as length of array was verified before parcelling.
863             Log.e("SipDelegateConfiguration", "exception reading address, returning null");
864             return null;
865         }
866     }
867 
868     @Override
describeContents()869     public int describeContents() {
870         return 0;
871     }
872 
873     public static final @NonNull Creator<SipDelegateConfiguration> CREATOR =
874             new Creator<SipDelegateConfiguration>() {
875         @Override
876         public SipDelegateConfiguration createFromParcel(Parcel source) {
877             return new SipDelegateConfiguration(source);
878         }
879 
880         @Override
881         public SipDelegateConfiguration[] newArray(int size) {
882             return new SipDelegateConfiguration[size];
883         }
884     };
885 
886     @Override
equals(Object o)887     public boolean equals(Object o) {
888         if (this == o) return true;
889         if (o == null || getClass() != o.getClass()) return false;
890         SipDelegateConfiguration that = (SipDelegateConfiguration) o;
891         return mVersion == that.mVersion
892                 && mTransportType == that.mTransportType
893                 && mIsSipCompactFormEnabled == that.mIsSipCompactFormEnabled
894                 && mIsSipKeepaliveEnabled == that.mIsSipKeepaliveEnabled
895                 && mMaxUdpPayloadSize == that.mMaxUdpPayloadSize
896                 && Objects.equals(mLocalAddress, that.mLocalAddress)
897                 && Objects.equals(mSipServerAddress, that.mSipServerAddress)
898                 && Objects.equals(mPublicUserIdentifier, that.mPublicUserIdentifier)
899                 && Objects.equals(mPrivateUserIdentifier, that.mPrivateUserIdentifier)
900                 && Objects.equals(mHomeDomain, that.mHomeDomain)
901                 && Objects.equals(mImei, that.mImei)
902                 && Objects.equals(mGruu, that.mGruu)
903                 && Objects.equals(mSipAuthHeader, that.mSipAuthHeader)
904                 && Objects.equals(mSipAuthNonce, that.mSipAuthNonce)
905                 && Objects.equals(mServiceRouteHeader, that.mServiceRouteHeader)
906                 && Objects.equals(mPathHeader, that.mPathHeader)
907                 && Objects.equals(mUserAgentHeader, that.mUserAgentHeader)
908                 && Objects.equals(mContactUserParam, that.mContactUserParam)
909                 && Objects.equals(mPaniHeader, that.mPaniHeader)
910                 && Objects.equals(mPlaniHeader, that.mPlaniHeader)
911                 && Objects.equals(mCniHeader, that.mCniHeader)
912                 && Objects.equals(mAssociatedUriHeader, that.mAssociatedUriHeader)
913                 && Objects.equals(mIpSecConfiguration, that.mIpSecConfiguration)
914                 && Objects.equals(mNatAddress, that.mNatAddress);
915     }
916 
917     @Override
hashCode()918     public int hashCode() {
919         return Objects.hash(mVersion, mTransportType, mLocalAddress, mSipServerAddress,
920                 mIsSipCompactFormEnabled, mIsSipKeepaliveEnabled, mMaxUdpPayloadSize,
921                 mPublicUserIdentifier, mPrivateUserIdentifier, mHomeDomain, mImei, mGruu,
922                 mSipAuthHeader, mSipAuthNonce, mServiceRouteHeader, mPathHeader, mUserAgentHeader,
923                 mContactUserParam, mPaniHeader, mPlaniHeader, mCniHeader, mAssociatedUriHeader,
924                 mIpSecConfiguration, mNatAddress);
925     }
926 
927     @Override
toString()928     public String toString() {
929         return "SipDelegateConfiguration{ mVersion=" + mVersion + ", mTransportType="
930                 + mTransportType + '}';
931     }
932 }
933