1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telephony.imsmedia;
18 
19 import android.annotation.IntDef;
20 import android.net.InetAddresses;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 import androidx.annotation.CallSuper;
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.net.InetSocketAddress;
31 import java.util.Objects;
32 
33 /**
34  * Class to encapsulate RTP (Real Time Protocol) configurations
35  *
36  * @hide
37  */
38 public abstract class RtpConfig implements Parcelable {
39     public static final int TYPE_AUDIO = 0;
40     public static final int TYPE_VIDEO = 1;
41     public static final int TYPE_TEXT = 2;
42 
43     /** Device neither transmits nor receives any RTP */
44     public static final int MEDIA_DIRECTION_NO_FLOW = 0;
45     /**
46      * Device transmits outgoing RTP but but doesn't receive incoming RTP.
47      * Eg. Other party muted the call
48      */
49     public static final int MEDIA_DIRECTION_SEND_ONLY = 1;
50     /**
51      * Device receives the incoming RTP but doesn't transmit any outgoing RTP.
52      * Eg. User muted the call
53      */
54     public static final int MEDIA_DIRECTION_RECEIVE_ONLY = 2;
55     /** Device transmits and receives RTP in both the Directions */
56     public static final int MEDIA_DIRECTION_SEND_RECEIVE = 3;
57     /** No RTP flow however RTCP continues to flow. Eg. HOLD */
58     public static final int MEDIA_DIRECTION_INACTIVE = 4;
59     /* definition of uninitialized port number*/
60     public static final int UNINITIALIZED_PORT = -1;
61 
62     /** @hide */
63     @IntDef(
64         value = {
65            MEDIA_DIRECTION_NO_FLOW,
66            MEDIA_DIRECTION_SEND_ONLY,
67            MEDIA_DIRECTION_RECEIVE_ONLY,
68            MEDIA_DIRECTION_SEND_RECEIVE,
69            MEDIA_DIRECTION_INACTIVE,
70     })
71     @Retention(RetentionPolicy.SOURCE)
72     public @interface MediaDirection {}
73 
74     private final int mType;
75     private @MediaDirection int mDirection;
76     private int mAccessNetwork;
77     @Nullable
78     private InetSocketAddress mRemoteRtpAddress;
79     @Nullable
80     private RtcpConfig mRtcpConfig;
81     private byte mDscp;
82     private byte mRxPayloadTypeNumber;
83     private byte mTxPayloadTypeNumber;
84     private byte mSamplingRateKHz;
85     /** Holds RTP parameters required to maintain RTP stream continuity */
86     @Nullable
87     private RtpContextParams mRtpContextParams;
88     @Nullable
89     private AnbrMode mAnbrMode;
90 
91     /** @hide */
RtpConfig(int type, Parcel in)92     RtpConfig(int type, Parcel in) {
93         mType = type;
94         mDirection = in.readInt();
95         mAccessNetwork = in.readInt();
96         mRemoteRtpAddress = readSocketAddress(in);
97         mRtcpConfig = in.readParcelable(RtcpConfig.class.getClassLoader(), RtcpConfig.class);
98         mDscp = in.readByte();
99         mRxPayloadTypeNumber = in.readByte();
100         mTxPayloadTypeNumber = in.readByte();
101         mSamplingRateKHz = in.readByte();
102         mRtpContextParams = in.readParcelable(RtpContextParams.class.getClassLoader(),
103                 RtpContextParams.class);
104         mAnbrMode = in.readParcelable(AnbrMode.class.getClassLoader(), AnbrMode.class);
105     }
106 
107     /** @hide **/
RtpConfig(int type, AbstractBuilder builder)108     RtpConfig(int type, AbstractBuilder builder) {
109         mType = type;
110         mDirection = builder.mDirection;
111         mAccessNetwork = builder.mAccessNetwork;
112         mRemoteRtpAddress = builder.mRemoteRtpAddress;
113         mRtcpConfig = builder.mRtcpConfig;
114         mDscp = builder.mDscp;
115         mRxPayloadTypeNumber = builder.mRxPayloadTypeNumber;
116         mTxPayloadTypeNumber = builder.mTxPayloadTypeNumber;
117         mSamplingRateKHz = builder.mSamplingRateKHz;
118         mRtpContextParams = builder.mRtpContextParams;
119         mAnbrMode = builder.mAnbrMode;
120     }
121 
readSocketAddress(final Parcel in)122     private @NonNull InetSocketAddress readSocketAddress(final Parcel in) {
123         final String address = in.readString();
124         final int port = in.readInt();
125         if(address != null && port != UNINITIALIZED_PORT) {
126             return new InetSocketAddress(
127                 InetAddresses.parseNumericAddress(address), port);
128         }
129         return null;
130     }
131 
getMediaType()132     public int getMediaType() {
133         return mType;
134     }
135 
getMediaDirection()136     public int getMediaDirection() {
137         return mDirection;
138     }
139 
setMediaDirection(final @MediaDirection int mDirection)140     public void setMediaDirection(final @MediaDirection int mDirection) {
141         this.mDirection = mDirection;
142     }
143 
getAccessNetwork()144     public int getAccessNetwork() {
145         return mAccessNetwork;
146     }
147 
setAccessNetwork(final int mAccessNetwork)148     public void setAccessNetwork(final int mAccessNetwork) {
149         this.mAccessNetwork = mAccessNetwork;
150     }
151 
getRemoteRtpAddress()152     public InetSocketAddress getRemoteRtpAddress() {
153         return mRemoteRtpAddress;
154     }
155 
setRemoteRtpAddress(final InetSocketAddress mRemoteRtpAddress)156     public void setRemoteRtpAddress(final InetSocketAddress mRemoteRtpAddress) {
157         this.mRemoteRtpAddress = mRemoteRtpAddress;
158     }
159 
getRtcpConfig()160     public RtcpConfig getRtcpConfig() {
161         return mRtcpConfig;
162     }
163 
setRtcpConfig(final RtcpConfig mRtcpConfig)164     public void setRtcpConfig(final RtcpConfig mRtcpConfig) {
165         this.mRtcpConfig = mRtcpConfig;
166     }
167 
getDscp()168     public byte getDscp() {
169         return mDscp;
170     }
171 
setDscp(final byte mDscp)172     public void setDscp(final byte mDscp) {
173         this.mDscp = mDscp;
174     }
175 
getRxPayloadTypeNumber()176     public byte getRxPayloadTypeNumber() {
177         return mRxPayloadTypeNumber;
178     }
179 
setRxPayloadTypeNumber(final byte mRxPayloadTypeNumber)180     public void setRxPayloadTypeNumber(final byte mRxPayloadTypeNumber) {
181         this.mRxPayloadTypeNumber = mRxPayloadTypeNumber;
182     }
183 
getTxPayloadTypeNumber()184     public byte getTxPayloadTypeNumber() {
185         return mTxPayloadTypeNumber;
186     }
187 
setTxPayloadTypeNumber(final byte mTxPayloadTypeNumber)188     public void setTxPayloadTypeNumber(final byte mTxPayloadTypeNumber) {
189         this.mTxPayloadTypeNumber = mTxPayloadTypeNumber;
190     }
191 
getSamplingRateKHz()192     public byte getSamplingRateKHz() {
193         return mSamplingRateKHz;
194     }
195 
setSamplingRateKHz(final byte mSamplingRateKHz)196     public void setSamplingRateKHz(final byte mSamplingRateKHz) {
197         this.mSamplingRateKHz = mSamplingRateKHz;
198     }
199 
getRtpContextParams()200     public RtpContextParams getRtpContextParams() {
201         return mRtpContextParams;
202     }
203 
setRtpContextParams(final RtpContextParams mRtpContextParams)204     public void setRtpContextParams(final RtpContextParams mRtpContextParams) {
205         this.mRtpContextParams = mRtpContextParams;
206     }
207 
getAnbrMode()208     public AnbrMode getAnbrMode() {
209         return mAnbrMode;
210     }
211 
setAnbrMode(final AnbrMode mAnbrMode)212     public void setAnbrMode(final AnbrMode mAnbrMode) {
213         this.mAnbrMode = mAnbrMode;
214     }
215 
216     @NonNull
217     @Override
toString()218     public String toString() {
219         return "RtpConfig: {mDirection=" + mDirection
220             + ", mAccessNetwork=" + mAccessNetwork
221             + ", mRemoteRtpAddress=" + mRemoteRtpAddress
222             + ", mRtcpConfig=" + mRtcpConfig
223             + ", mDscp=" + mDscp
224             + ", mRxPayloadTypeNumber=" + mRxPayloadTypeNumber
225             + ", mTxPayloadTypeNumber=" + mTxPayloadTypeNumber
226             + ", mSamplingRateKHz=" + mSamplingRateKHz
227             + ", mRtpContextParams=" + mRtpContextParams
228             + ", mAnbrMode=" + mAnbrMode
229             + " }";
230     }
231 
232     @Override
hashCode()233     public int hashCode() {
234         return Objects.hash(mDirection, mAccessNetwork, mRemoteRtpAddress, mRtcpConfig,
235             mDscp, mRxPayloadTypeNumber, mTxPayloadTypeNumber, mSamplingRateKHz, mRtpContextParams,
236             mAnbrMode);
237     }
238 
239     @Override
equals(@ullable Object o)240     public boolean equals(@Nullable Object o) {
241         if (o == null || !(o instanceof RtpConfig) || hashCode() != o.hashCode()) {
242             return false;
243         }
244 
245         if (this == o) {
246             return true;
247         }
248 
249         RtpConfig s = (RtpConfig) o;
250 
251         return (mDirection == s.mDirection
252                 && mAccessNetwork == s.mAccessNetwork
253                 && Objects.equals(mRemoteRtpAddress, s.mRemoteRtpAddress)
254                 && Objects.equals(mRtcpConfig, s.mRtcpConfig)
255                 && mDscp == s.mDscp
256                 && mRxPayloadTypeNumber == s.mRxPayloadTypeNumber
257                 && mTxPayloadTypeNumber == s.mTxPayloadTypeNumber
258                 && mSamplingRateKHz == s.mSamplingRateKHz
259                 && Objects.equals(mRtpContextParams, s.mRtpContextParams)
260                 && Objects.equals(mAnbrMode, s.mAnbrMode));
261     }
262 
263     /**
264      * {@link Parcelable#describeContents}
265      */
describeContents()266     public int describeContents() {
267         return 0;
268     }
269 
270     /**
271      * Used by child classes for parceling.
272      *
273      * @hide
274      */
275     @CallSuper
writeToParcel(Parcel dest, int type)276     public void writeToParcel(Parcel dest, int type) {
277         dest.writeInt(type);
278         dest.writeInt(mDirection);
279         dest.writeInt(mAccessNetwork);
280         if (mRemoteRtpAddress == null) {
281             dest.writeString(null);
282             dest.writeInt(UNINITIALIZED_PORT);
283         } else {
284             dest.writeString(mRemoteRtpAddress.getAddress().getHostAddress());
285             dest.writeInt(mRemoteRtpAddress.getPort());
286         }
287         dest.writeParcelable(mRtcpConfig, 0);
288         dest.writeByte(mDscp);
289         dest.writeByte(mRxPayloadTypeNumber);
290         dest.writeByte(mTxPayloadTypeNumber);
291         dest.writeByte(mSamplingRateKHz);
292         dest.writeParcelable(mRtpContextParams, 0);
293         dest.writeParcelable(mAnbrMode, 0);
294     }
295 
296     public static final @NonNull Parcelable.Creator<RtpConfig>
297             CREATOR = new Parcelable.Creator() {
298                 public RtpConfig createFromParcel(Parcel in) {
299                     int type = in.readInt();
300                     switch (type) {
301                         case TYPE_AUDIO:
302                             return new AudioConfig(in);
303                         case TYPE_VIDEO:
304                             return new VideoConfig(in);
305                         case TYPE_TEXT:
306                             return new TextConfig(in);
307                         default:
308                             throw new IllegalArgumentException("Bad Type Parcel");
309                     }
310                 }
311 
312                 public RtpConfig[] newArray(int size) {
313                     return new RtpConfig[size];
314                 }
315             };
316 
317     /**
318      * Provides a convenient way to set the fields of a {@link RtpConfig}
319      * when creating a new instance.
320      */
321     public static abstract class AbstractBuilder<T extends AbstractBuilder<T>> {
322         private @MediaDirection int mDirection;
323         private int mAccessNetwork;
324         @Nullable
325         private InetSocketAddress mRemoteRtpAddress;
326         @Nullable
327         private RtcpConfig mRtcpConfig;
328         private byte mDscp;
329         private byte mRxPayloadTypeNumber;
330         private byte mTxPayloadTypeNumber;
331         private byte mSamplingRateKHz;
332         @Nullable
333         private RtpContextParams mRtpContextParams;
334         private AnbrMode mAnbrMode;
335 
AbstractBuilder()336         AbstractBuilder() {}
337 
338         /** Returns {@code this} */
self()339         abstract T self();
340 
341         /**
342          * Sets media flow direction of {@link MediaDirection}
343          * @param direction direction of media.
344          */
setMediaDirection(final @MediaDirection int direction)345         public T setMediaDirection(final @MediaDirection int direction) {
346             this.mDirection = direction;
347             return self();
348         }
349 
350         /**
351          * Sets radio access metwork type
352          * @param accessNetwork network type
353          */
setAccessNetwork(final int accessNetwork)354         public T setAccessNetwork(final int accessNetwork) {
355             this.mAccessNetwork = accessNetwork;
356             return self();
357         }
358 
359         /**
360          * Sets Ip address and port number of the other party for RTP media.
361          * @param remoteRtpAddress ip address and port form of InetSocketAddress
362          */
setRemoteRtpAddress(final InetSocketAddress remoteRtpAddress)363         public T setRemoteRtpAddress(final InetSocketAddress remoteRtpAddress) {
364             this.mRemoteRtpAddress = remoteRtpAddress;
365             return self();
366         }
367 
368         /**
369          * Sets rtcp configuration
370          * @param rtcpConfig configuration fields of a {@link RtcpConfig}
371          */
setRtcpConfig(final RtcpConfig rtcpConfig)372         public T setRtcpConfig(final RtcpConfig rtcpConfig) {
373             this.mRtcpConfig = rtcpConfig;
374             return self();
375         }
376 
377         /**
378          * Sets a dscp: Differentiated Services Field Code Point value, see RFC 2474
379          * @param dscp dscp value
380          */
setDscp(final byte dscp)381         public T setDscp(final byte dscp) {
382             this.mDscp = dscp;
383             return self();
384         }
385 
386         /**
387          * Sets static or dynamic payload type number negotiated through the SDP for
388          * the incoming RTP packets. This value shall be matched with the PT value
389          * of the incoming RTP header. Values 0 to 127, see RFC 3551 section 6.
390          * @param rxPayloadTypeNumber payload type number.
391          */
setRxPayloadTypeNumber(final byte rxPayloadTypeNumber)392         public T setRxPayloadTypeNumber(final byte rxPayloadTypeNumber) {
393             this.mRxPayloadTypeNumber = rxPayloadTypeNumber;
394             return self();
395         }
396 
397         /**
398          * Sets static or dynamic payload type number negotiated through the SDP for
399          * the outgoing RTP packets. This value shall be set to the PT value
400          * of the outgoing RTP header. Values 0 to 127, see RFC 3551 section 6.
401          * @param txPayloadTypeNumber payload type number.
402          */
setTxPayloadTypeNumber(final byte txPayloadTypeNumber)403         public T setTxPayloadTypeNumber(final byte txPayloadTypeNumber) {
404             this.mTxPayloadTypeNumber = txPayloadTypeNumber;
405             return self();
406         }
407 
408         /**
409          * Sets media source sampling rate in kHz.
410          * @param samplingRateKHz sampling rate.
411          */
setSamplingRateKHz(final byte samplingRateKHz)412         public T setSamplingRateKHz(final byte samplingRateKHz) {
413             this.mSamplingRateKHz = samplingRateKHz;
414             return self();
415         }
416 
417         /**
418          * Sets RTP parameters required for RTP context transfer
419          * @param rtpContextParams parameter fields of a {@link RtpContextParams}
420          */
setRtpContextParams(final RtpContextParams rtpContextParams)421         public T setRtpContextParams(final RtpContextParams rtpContextParams) {
422             this.mRtpContextParams = rtpContextParams;
423             return self();
424         }
425 
426         /**
427          * Sets AnbrMode information
428          * @param anbrMode The codec mode of the current negotiated codec (either Evs or Amr)
429          */
setAnbrMode(final AnbrMode anbrMode)430         public T setAnbrMode(final AnbrMode anbrMode) {
431             this.mAnbrMode = anbrMode;
432             return self();
433         }
434     }
435 }
436