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 androidx.annotation.NonNull;
21 import androidx.annotation.Nullable;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Objects;
28 
29 /**
30  * The class represents RTCP (Real Time Control Protocol) configurations.
31  *
32  * @hide
33  */
34 public final class RtcpConfig implements Parcelable {
35     /**
36      * RTCP XR (extended report) types are not specified,
37      * See RFC 3611 section 4
38      */
39     public static final int FLAG_RTCPXR_NONE = 0;
40     /**
41      * RTCP XR type Loss RLE Report Block as specified in
42      * RFC 3611 section 4.1
43      */
44     public static final int FLAG_RTCPXR_LOSS_RLE_REPORT_BLOCK = 1 << 0;
45     /**
46      * RTCP XR type Duplicate RLE Report Block as specified in
47      * RFC 3611 section 4.2
48      */
49     public static final int FLAG_RTCPXR_DUPLICATE_RLE_REPORT_BLOCK = 1 << 1;
50     /**
51      * RTCP XR type Packet Receipt Times Report Block as specified in
52      * RFC 3611 section 4.3
53      */
54     public static final int FLAG_RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK = 1 << 2;
55     /**
56      * RTCP XR type Receiver Reference Time Report Block as specified in
57      * RFC 3611 section 4.4
58      */
59     public static final int FLAG_RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK = 1 << 3;
60     /**
61      * RTCP XR type DLRR Report Block as specified in
62      * RFC 3611 section 4.5
63      */
64     public static final int FLAG_RTCPXR_DLRR_REPORT_BLOCK = 1 << 4;
65     /**
66      * RTCP XR type Statistics Summary Report Block as specified in
67      * RFC 3611 section 4.6
68      */
69     public static final int FLAG_RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK = 1 << 5;
70     /**
71      * RTCP XR type VoIP Metrics Report Block as specified in
72      * RFC 3611 section 4.7
73      */
74     public static final int FLAG_RTCPXR_VOIP_METRICS_REPORT_BLOCK = 1 << 6;
75 
76     /** Canonical name that will be sent to all session participants */
77     private final String canonicalName;
78 
79     /** UDP port number for sending outgoing RTCP packets */
80     private final int transmitPort;
81 
82     /**
83      * RTCP transmit interval in seconds. The value 0 indicates that RTCP
84      * reports shall not be sent to the other party.
85      */
86     private final int intervalSec;
87 
88     /** @hide */
89     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
90         FLAG_RTCPXR_NONE,
91         FLAG_RTCPXR_LOSS_RLE_REPORT_BLOCK,
92         FLAG_RTCPXR_DUPLICATE_RLE_REPORT_BLOCK,
93         FLAG_RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK,
94         FLAG_RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK,
95         FLAG_RTCPXR_DLRR_REPORT_BLOCK,
96         FLAG_RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK,
97         FLAG_RTCPXR_VOIP_METRICS_REPORT_BLOCK,
98     })
99     @Retention(RetentionPolicy.SOURCE)
100     public @interface RtcpXrBlockType {}
101 
102     /** Bitmask of RTCP-XR blocks to be enabled */
103     private final @RtcpXrBlockType int rtcpXrBlockTypes;
104 
105     /** @hide **/
RtcpConfig(Parcel in)106     private RtcpConfig(Parcel in) {
107         canonicalName = in.readString();
108         transmitPort = in.readInt();
109         intervalSec = in.readInt();
110         rtcpXrBlockTypes = in.readInt();
111     }
112 
113     /** @hide **/
RtcpConfig(final String canonicalName, final int transmitPort, final int intervalSec, final @RtcpXrBlockType int rtcpXrBlockTypes)114     private RtcpConfig(final String canonicalName, final int transmitPort, final int intervalSec,
115             final @RtcpXrBlockType int rtcpXrBlockTypes) {
116         this.canonicalName = canonicalName;
117         this.transmitPort = transmitPort;
118         this.intervalSec = intervalSec;
119         this.rtcpXrBlockTypes = rtcpXrBlockTypes;
120     }
121 
122     /** @hide **/
getCanonicalName()123     public String getCanonicalName() {
124         return canonicalName;
125     }
126 
127     /** @hide **/
getTransmitPort()128     public int getTransmitPort() {
129         return transmitPort;
130     }
131 
132     /** @hide **/
getIntervalSec()133     public int getIntervalSec() {
134         return intervalSec;
135     }
136 
137     /** @hide **/
getRtcpXrBlockTypes()138     public @RtcpXrBlockType int getRtcpXrBlockTypes() {
139         return rtcpXrBlockTypes;
140     }
141 
142     @NonNull
143     @Override
toString()144     public String toString() {
145         return "RtcpConfig: {canonicalName=" + canonicalName
146                 + ", transmitPort=" + transmitPort
147                 + ", intervalSec=" + intervalSec
148                 + ", rtcpXrBlockTypes=" + rtcpXrBlockTypes
149                 + " }";
150     }
151 
152     @Override
hashCode()153     public int hashCode() {
154         return Objects.hash(canonicalName, transmitPort, intervalSec, rtcpXrBlockTypes);
155     }
156 
157     @Override
equals(@ullable Object o)158     public boolean equals(@Nullable Object o) {
159         if (o == null || !(o instanceof RtcpConfig) || hashCode() != o.hashCode()) {
160             return false;
161         }
162 
163         if (this == o) {
164             return true;
165         }
166 
167         RtcpConfig s = (RtcpConfig) o;
168 
169         return (Objects.equals(canonicalName, s.canonicalName)
170                 && transmitPort == s.transmitPort
171                 && intervalSec == s.intervalSec
172                 && rtcpXrBlockTypes == s.rtcpXrBlockTypes);
173     }
174 
175     /**
176      * {@link Parcelable#describeContents}
177      */
describeContents()178     public int describeContents() {
179         return 0;
180     }
181 
182     /**
183      * {@link Parcelable#writeToParcel}
184      */
writeToParcel(Parcel dest, int flags)185     public void writeToParcel(Parcel dest, int flags) {
186         dest.writeString(canonicalName);
187         dest.writeInt(transmitPort);
188         dest.writeInt(intervalSec);
189         dest.writeInt(rtcpXrBlockTypes);
190     }
191 
192     public static final @NonNull Parcelable.Creator<RtcpConfig>
193         CREATOR = new Parcelable.Creator() {
194         public RtcpConfig createFromParcel(Parcel in) {
195             // TODO use builder class so it will validate
196             return new RtcpConfig(in);
197         }
198 
199         public RtcpConfig[] newArray(int size) {
200             return new RtcpConfig[size];
201         }
202     };
203 
204     /**
205      * Provides a convenient way to set the fields of a {@link RtcpConfig}
206      * when creating a new instance.
207      */
208     public static final class Builder {
209         private String canonicalName;
210         private int transmitPort;
211         private int intervalSec;
212         private @RtcpXrBlockType int rtcpXrBlockTypes;
213 
214         /**
215          * Default constructor for Builder.
216          */
Builder()217         public Builder() {
218         }
219 
220         /**
221          * Set the canonical name which will be sent to all session participants.
222          *
223          * @param canonicalName The canonical name.
224          * @return The same instance of the builder.
225          */
setCanonicalName(final String canonicalName)226         public @NonNull Builder setCanonicalName(final String canonicalName) {
227             this.canonicalName = canonicalName;
228             return this;
229         }
230 
231         /**
232          * Set the UDP port number for sending outgoing RTCP packets.
233          *
234          * @param transmitPort The UDP port number for outgoing RTCP packets.
235          * @return The same instance of the builder.
236          */
setTransmitPort(final int transmitPort)237         public @NonNull Builder setTransmitPort(final int transmitPort) {
238             this.transmitPort = transmitPort;
239             return this;
240         }
241 
242         /**
243          * Set the RTCP transmit interval in seconds. The value 0 indicates that RTCP
244          * reports shall not be sent to the other party.
245          *
246          * @param intervalSec RTCP transmit interval in seconds.
247          * @return The same instance of the builder.
248          */
setIntervalSec(final int intervalSec)249         public @NonNull Builder setIntervalSec(final int intervalSec) {
250             this.intervalSec = intervalSec;
251             return this;
252         }
253 
254         /**
255          * Set the bitmask of RTCP-XR blocks to be enabled, See RFC 3611 section 4.
256          *
257          * @param rtcpXrBlockTypes RTCP-XR blocks to be enabled.
258          * @return The same instance of the builder.
259          */
setRtcpXrBlockTypes(final @RtcpXrBlockType int rtcpXrBlockTypes)260         public @NonNull Builder setRtcpXrBlockTypes(final @RtcpXrBlockType int rtcpXrBlockTypes) {
261             this.rtcpXrBlockTypes = rtcpXrBlockTypes;
262             return this;
263         }
264 
265         /**
266          * Build the RtcpConfig.
267          *
268          * @return the RtcpConfig object.
269          */
build()270         public @NonNull RtcpConfig build() {
271             // TODO validation
272             return new RtcpConfig(canonicalName, transmitPort, intervalSec, rtcpXrBlockTypes);
273         }
274     }
275 }
276 
277