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.os.Parcel; 21 import android.os.Parcelable; 22 23 import androidx.annotation.NonNull; 24 import androidx.annotation.Nullable; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 30 /** 31 * The class represents RTP (Real Time Control) configuration for audio stream. 32 * 33 * @hide 34 */ 35 public final class AudioConfig extends RtpConfig { 36 /** Adaptive Multi-Rate */ 37 public static final int CODEC_AMR = android.hardware.radio.ims.media.CodecType.AMR; 38 /** Adaptive Multi-Rate Wide Band */ 39 public static final int CODEC_AMR_WB = android.hardware.radio.ims.media.CodecType.AMR_WB; 40 /** Enhanced Voice Services */ 41 public static final int CODEC_EVS = android.hardware.radio.ims.media.CodecType.EVS; 42 /** G.711 A-law i.e. Pulse Code Modulation using A-law */ 43 public static final int CODEC_PCMA = android.hardware.radio.ims.media.CodecType.PCMA; 44 /** G.711 μ-law i.e. Pulse Code Modulation using μ-law */ 45 public static final int CODEC_PCMU = android.hardware.radio.ims.media.CodecType.PCMU; 46 47 /** @hide */ 48 @IntDef( 49 flag = true, 50 value = { 51 CODEC_AMR, 52 CODEC_AMR_WB, 53 CODEC_EVS, 54 CODEC_PCMA, 55 CODEC_PCMU, 56 }) 57 @Retention(RetentionPolicy.SOURCE) 58 public @interface CodecType {} 59 60 private byte pTimeMillis; 61 private int maxPtimeMillis; 62 private boolean dtxEnabled; 63 private @CodecType int codecType; 64 private byte mDtmfTxPayloadTypeNumber; 65 private byte mDtmfRxPayloadTypeNumber; 66 private byte dtmfSamplingRateKHz; 67 @Nullable 68 private AmrParams amrParams; 69 @Nullable 70 private EvsParams evsParams; 71 72 /** @hide */ AudioConfig(Parcel in)73 AudioConfig(Parcel in) { 74 super(RtpConfig.TYPE_AUDIO, in); 75 pTimeMillis = in.readByte(); 76 maxPtimeMillis = in.readInt(); 77 dtxEnabled = in.readBoolean(); 78 codecType = in.readInt(); 79 mDtmfTxPayloadTypeNumber = in.readByte(); 80 mDtmfRxPayloadTypeNumber = in.readByte(); 81 dtmfSamplingRateKHz = in.readByte(); 82 amrParams = in.readParcelable(AmrParams.class.getClassLoader(), AmrParams.class); 83 evsParams = in.readParcelable(EvsParams.class.getClassLoader(), EvsParams.class); 84 } 85 86 /** @hide */ AudioConfig(Builder builder)87 AudioConfig(Builder builder) { 88 super(RtpConfig.TYPE_AUDIO, builder); 89 this.pTimeMillis = builder.pTimeMillis; 90 this.maxPtimeMillis = builder.maxPtimeMillis; 91 this.dtxEnabled = builder.dtxEnabled; 92 this.codecType = builder.codecType; 93 this.mDtmfTxPayloadTypeNumber = builder.mDtmfTxPayloadTypeNumber; 94 this.mDtmfRxPayloadTypeNumber = builder.mDtmfRxPayloadTypeNumber; 95 this.dtmfSamplingRateKHz = builder.dtmfSamplingRateKHz; 96 this.amrParams = builder.amrParams; 97 this.evsParams = builder.evsParams; 98 } 99 100 /** @hide **/ getPtimeMillis()101 public byte getPtimeMillis() { 102 return pTimeMillis; 103 } 104 105 /** @hide **/ setPtimeMillis(byte pTimeMillis)106 public void setPtimeMillis(byte pTimeMillis) { 107 this.pTimeMillis = pTimeMillis; 108 } 109 110 /** @hide **/ getMaxPtimeMillis()111 public int getMaxPtimeMillis() { 112 return maxPtimeMillis; 113 } 114 115 /** @hide **/ setMaxPtimeMillis(int maxPtimeMillis)116 public void setMaxPtimeMillis(int maxPtimeMillis) { 117 this.maxPtimeMillis = maxPtimeMillis; 118 } 119 120 /** @hide **/ getDtxEnabled()121 public boolean getDtxEnabled() { 122 return dtxEnabled; 123 } 124 125 /** @hide **/ setDtxEnabled(boolean dtxEnabled)126 public void setDtxEnabled(boolean dtxEnabled) { 127 this.dtxEnabled = dtxEnabled; 128 } 129 130 /** @hide **/ getCodecType()131 public int getCodecType() { 132 return codecType; 133 } 134 135 /** @hide **/ setCodecType(int codecType)136 public void setCodecType(int codecType) { 137 this.codecType = codecType; 138 } 139 140 /** @hide **/ getTxDtmfPayloadTypeNumber()141 public byte getTxDtmfPayloadTypeNumber() { 142 return mDtmfTxPayloadTypeNumber; 143 } 144 145 /** @hide **/ getRxDtmfPayloadTypeNumber()146 public byte getRxDtmfPayloadTypeNumber() { 147 return mDtmfRxPayloadTypeNumber; 148 } 149 150 /** @hide **/ setTxDtmfPayloadTypeNumber(byte dtmfTxPayloadTypeNumber)151 public void setTxDtmfPayloadTypeNumber(byte dtmfTxPayloadTypeNumber) { 152 this.mDtmfTxPayloadTypeNumber = dtmfTxPayloadTypeNumber; 153 } 154 155 /** @hide **/ setRxDtmfPayloadTypeNumber(byte dtmfRxPayloadTypeNumber)156 public void setRxDtmfPayloadTypeNumber(byte dtmfRxPayloadTypeNumber) { 157 this.mDtmfRxPayloadTypeNumber = dtmfRxPayloadTypeNumber; 158 } 159 160 /** @hide **/ getDtmfSamplingRateKHz()161 public byte getDtmfSamplingRateKHz() { 162 return dtmfSamplingRateKHz; 163 } 164 165 /** @hide **/ setDtmfSamplingRateKHz(byte dtmfSamplingRateKHz)166 public void setDtmfSamplingRateKHz(byte dtmfSamplingRateKHz) { 167 this.dtmfSamplingRateKHz = dtmfSamplingRateKHz; 168 } 169 170 /** @hide **/ getAmrParams()171 public AmrParams getAmrParams() { 172 return amrParams; 173 } 174 175 /** @hide **/ getEvsParams()176 public EvsParams getEvsParams() { 177 return evsParams; 178 } 179 180 @NonNull 181 @Override toString()182 public String toString() { 183 return super.toString() + " AudioConfig: {pTimeMillis=" + pTimeMillis 184 + ", maxPtimeMillis=" + maxPtimeMillis 185 + ", dtxEnabled=" + dtxEnabled 186 + ", codecType=" + codecType 187 + ", mDtmfTxPayloadTypeNumber=" + mDtmfTxPayloadTypeNumber 188 + ", mDtmfRxPayloadTypeNumber=" + mDtmfRxPayloadTypeNumber 189 + ", dtmfSamplingRateKHz=" + dtmfSamplingRateKHz 190 + ", amrParams=" + amrParams 191 + ", evsParams=" + evsParams 192 + " }"; 193 } 194 195 @Override hashCode()196 public int hashCode() { 197 return Objects.hash(super.hashCode(), pTimeMillis, maxPtimeMillis, 198 dtxEnabled, codecType, mDtmfTxPayloadTypeNumber, 199 mDtmfRxPayloadTypeNumber, dtmfSamplingRateKHz, amrParams, evsParams); 200 } 201 202 @Override equals(@ullable Object o)203 public boolean equals(@Nullable Object o) { 204 if (o == null || !(o instanceof AudioConfig) || hashCode() != o.hashCode()) { 205 return false; 206 } 207 208 if (this == o) { 209 return true; 210 } 211 212 AudioConfig s = (AudioConfig) o; 213 214 if (!super.equals(s)) { 215 return false; 216 } 217 218 return (pTimeMillis == s.pTimeMillis 219 && maxPtimeMillis == s.maxPtimeMillis 220 && dtxEnabled == s.dtxEnabled 221 && codecType == s.codecType 222 && mDtmfTxPayloadTypeNumber == s.mDtmfTxPayloadTypeNumber 223 && mDtmfRxPayloadTypeNumber == s.mDtmfRxPayloadTypeNumber 224 && dtmfSamplingRateKHz == s.dtmfSamplingRateKHz 225 && Objects.equals(amrParams, s.amrParams) 226 && Objects.equals(evsParams, s.evsParams)); 227 } 228 229 /** 230 * {@link Parcelable#describeContents} 231 */ describeContents()232 public int describeContents() { 233 return 0; 234 } 235 236 /** 237 * {@link Parcelable#writeToParcel} 238 */ writeToParcel(Parcel dest, int flags)239 public void writeToParcel(Parcel dest, int flags) { 240 super.writeToParcel(dest, RtpConfig.TYPE_AUDIO); 241 dest.writeByte(pTimeMillis); 242 dest.writeInt(maxPtimeMillis); 243 dest.writeBoolean(dtxEnabled); 244 dest.writeInt(codecType); 245 dest.writeByte(mDtmfTxPayloadTypeNumber); 246 dest.writeByte(mDtmfRxPayloadTypeNumber); 247 dest.writeByte(dtmfSamplingRateKHz); 248 dest.writeParcelable(amrParams, 0); 249 dest.writeParcelable(evsParams, 0); 250 } 251 252 public static final @NonNull Parcelable.Creator<AudioConfig> 253 CREATOR = new Parcelable.Creator() { 254 public AudioConfig createFromParcel(Parcel in) { 255 in.readInt(); //skip 256 return new AudioConfig(in); 257 } 258 259 public AudioConfig[] newArray(int size) { 260 return new AudioConfig[size]; 261 } 262 }; 263 264 /** 265 * Provides a convenient way to set the fields of a {@link AudioConfig} 266 * when creating a new instance. 267 */ 268 public static final class Builder extends RtpConfig.AbstractBuilder<Builder> { 269 private byte pTimeMillis; 270 private int maxPtimeMillis; 271 private boolean dtxEnabled; 272 private @CodecType int codecType; 273 private byte mDtmfTxPayloadTypeNumber; 274 private byte mDtmfRxPayloadTypeNumber; 275 private byte dtmfSamplingRateKHz; 276 @Nullable 277 private AmrParams amrParams; 278 @Nullable 279 private EvsParams evsParams; 280 281 /** 282 * Default constructor for Builder. 283 */ Builder()284 public Builder() { 285 } 286 287 @Override self()288 Builder self() { 289 return this; 290 } 291 292 /** 293 * Set the packet time i.e. recommended length of time in milliseconds 294 * represented by the media in each packet, see RFC 4566 295 * 296 * @param pTimeMillis packet time 297 * @return The same instance of the builder 298 */ setPtimeMillis(final byte pTimeMillis)299 public Builder setPtimeMillis(final byte pTimeMillis) { 300 this.pTimeMillis = pTimeMillis; 301 return this; 302 } 303 304 /** 305 * Set the maximum amount of media that can be encapsulated in each packet 306 * represented in milliseconds, see RFC 4566 307 * 308 * @param maxPtimeMillis maximum packet time 309 * @return The same instance of the builder 310 */ setMaxPtimeMillis(final int maxPtimeMillis)311 public Builder setMaxPtimeMillis(final int maxPtimeMillis) { 312 this.maxPtimeMillis = maxPtimeMillis; 313 return this; 314 } 315 316 /** 317 * Set whether discontinuous transmission (DTX) is enabled or not 318 * 319 * @param dtxEnabled {@code true} if DTX enabled 320 * @return The same instance of the builder 321 */ setDtxEnabled(final boolean dtxEnabled)322 public Builder setDtxEnabled(final boolean dtxEnabled) { 323 this.dtxEnabled = dtxEnabled; 324 return this; 325 } 326 327 /** 328 * Set the negotiated audio codec 329 * 330 * @param codecType codec type 331 * @return The same instance of the builder 332 */ setCodecType(final @CodecType int codecType)333 public Builder setCodecType(final @CodecType int codecType) { 334 this.codecType = codecType; 335 return this; 336 } 337 338 /** 339 * Set the dynamic Tx payload type number to be used to transmit DTMF RTP packets. 340 * The values is in the range from 96 to 127 chosen during the session establishment. 341 * The PT value of the RTP header of all DTMF packets shall be set with this value. 342 * 343 * @param dtmfTxPayloadTypeNumber Payload type number for the Tx DTMF packets 344 * @return The same instance of the builder 345 */ setTxDtmfPayloadTypeNumber(final byte dtmfTxPayloadTypeNumber)346 public Builder setTxDtmfPayloadTypeNumber(final byte dtmfTxPayloadTypeNumber) { 347 this.mDtmfTxPayloadTypeNumber = dtmfTxPayloadTypeNumber; 348 return this; 349 } 350 351 /** 352 * Set the dynamic Rx payload type number to be used for DTMF received RTP packets. 353 * The values is in the range from 96 to 127 chosen during the session establishment. 354 * The PT value of the RTP header of all DTMF packets shall be set with this value. 355 * 356 * @param dtmfRxPayloadTypeNumber Payload type number for the Rx DTMF packets 357 * @return The same instance of the builder 358 */ setRxDtmfPayloadTypeNumber(final byte dtmfRxPayloadTypeNumber)359 public Builder setRxDtmfPayloadTypeNumber(final byte dtmfRxPayloadTypeNumber) { 360 this.mDtmfRxPayloadTypeNumber = dtmfRxPayloadTypeNumber; 361 return this; 362 } 363 364 /** 365 * Set the DTMF sampling rate on this media stream 366 * 367 * @param dtmfSamplingRateKHz DTMF sampling rate 368 * @return The same instance of the builder 369 */ setDtmfSamplingRateKHz(final byte dtmfSamplingRateKHz)370 public Builder setDtmfSamplingRateKHz(final byte dtmfSamplingRateKHz) { 371 this.dtmfSamplingRateKHz = dtmfSamplingRateKHz; 372 return this; 373 } 374 375 /** 376 * Set the AMR codec parameters, see {@link AmrParams} 377 * 378 * @param amrParams AMR parameters 379 * @return The same instance of the builder 380 */ setAmrParams(final AmrParams amrParams)381 public Builder setAmrParams(final AmrParams amrParams) { 382 this.amrParams = amrParams; 383 return this; 384 } 385 386 /** 387 * Set the EVS codec parameters, see {@link EvsParams} 388 * 389 * @param evsParams EVS parameters. 390 * @return The same instance of the builder 391 */ setEvsParams(final EvsParams evsParams)392 public Builder setEvsParams(final EvsParams evsParams) { 393 this.evsParams = evsParams; 394 return this; 395 } 396 397 /** 398 * Build the AudioConfig. 399 * 400 * @return the AudioConfig object. 401 */ build()402 public @NonNull AudioConfig build() { 403 // TODO validation 404 return new AudioConfig(this); 405 } 406 } 407 } 408 409