1 /* 2 * Copyright (C) 2018 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; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 import java.util.Objects; 30 31 /** 32 * Parcelable object to handle call quality. 33 * <p> 34 * Currently this supports IMS calls. 35 * <p> 36 * It provides the call quality level, duration, and additional information related to RTP packets, 37 * jitter and delay. 38 * <p> 39 * If there are multiple active calls, the CallQuality will pertain to the call in the foreground. 40 * 41 * @hide 42 */ 43 @SystemApi 44 @TestApi 45 public final class CallQuality implements Parcelable { 46 47 // Constants representing the call quality level (see #CallQuality); 48 public static final int CALL_QUALITY_EXCELLENT = 0; 49 public static final int CALL_QUALITY_GOOD = 1; 50 public static final int CALL_QUALITY_FAIR = 2; 51 public static final int CALL_QUALITY_POOR = 3; 52 public static final int CALL_QUALITY_BAD = 4; 53 public static final int CALL_QUALITY_NOT_AVAILABLE = 5; 54 55 /** 56 * Call quality 57 * @hide 58 */ 59 @IntDef(prefix = { "CALL_QUALITY_" }, value = { 60 CALL_QUALITY_EXCELLENT, 61 CALL_QUALITY_GOOD, 62 CALL_QUALITY_FAIR, 63 CALL_QUALITY_POOR, 64 CALL_QUALITY_BAD, 65 CALL_QUALITY_NOT_AVAILABLE, 66 }) 67 @Retention(RetentionPolicy.SOURCE) 68 public @interface CallQualityLevel {} 69 70 @CallQualityLevel 71 private int mDownlinkCallQualityLevel; 72 @CallQualityLevel 73 private int mUplinkCallQualityLevel; 74 private int mCallDuration; 75 private int mNumRtpPacketsTransmitted; 76 private int mNumRtpPacketsReceived; 77 private int mNumRtpPacketsTransmittedLost; 78 private int mNumRtpPacketsNotReceived; 79 private int mAverageRelativeJitter; 80 private int mMaxRelativeJitter; 81 private int mAverageRoundTripTime; 82 private int mCodecType; 83 private boolean mRtpInactivityDetected; 84 private boolean mRxSilenceDetected; 85 private boolean mTxSilenceDetected; 86 87 /** @hide **/ CallQuality(Parcel in)88 public CallQuality(Parcel in) { 89 mDownlinkCallQualityLevel = in.readInt(); 90 mUplinkCallQualityLevel = in.readInt(); 91 mCallDuration = in.readInt(); 92 mNumRtpPacketsTransmitted = in.readInt(); 93 mNumRtpPacketsReceived = in.readInt(); 94 mNumRtpPacketsTransmittedLost = in.readInt(); 95 mNumRtpPacketsNotReceived = in.readInt(); 96 mAverageRelativeJitter = in.readInt(); 97 mMaxRelativeJitter = in.readInt(); 98 mAverageRoundTripTime = in.readInt(); 99 mCodecType = in.readInt(); 100 mRtpInactivityDetected = in.readBoolean(); 101 mRxSilenceDetected = in.readBoolean(); 102 mTxSilenceDetected = in.readBoolean(); 103 } 104 105 /** @hide **/ CallQuality()106 public CallQuality() { 107 } 108 109 /** 110 * Constructor. 111 * 112 * @param callQualityLevel the call quality level (see #CallQualityLevel) 113 * @param callDuration the call duration in milliseconds 114 * @param numRtpPacketsTransmitted RTP packets sent to network 115 * @param numRtpPacketsReceived RTP packets received from network 116 * @param numRtpPacketsTransmittedLost RTP packets which were lost in network and never 117 * transmitted 118 * @param numRtpPacketsNotReceived RTP packets which were lost in network and never received 119 * @param averageRelativeJitter average relative jitter in milliseconds 120 * @param maxRelativeJitter maximum relative jitter in milliseconds 121 * @param averageRoundTripTime average round trip delay in milliseconds 122 * @param codecType the codec type 123 */ CallQuality( @allQualityLevel int downlinkCallQualityLevel, @CallQualityLevel int uplinkCallQualityLevel, int callDuration, int numRtpPacketsTransmitted, int numRtpPacketsReceived, int numRtpPacketsTransmittedLost, int numRtpPacketsNotReceived, int averageRelativeJitter, int maxRelativeJitter, int averageRoundTripTime, int codecType)124 public CallQuality( 125 @CallQualityLevel int downlinkCallQualityLevel, 126 @CallQualityLevel int uplinkCallQualityLevel, 127 int callDuration, 128 int numRtpPacketsTransmitted, 129 int numRtpPacketsReceived, 130 int numRtpPacketsTransmittedLost, 131 int numRtpPacketsNotReceived, 132 int averageRelativeJitter, 133 int maxRelativeJitter, 134 int averageRoundTripTime, 135 int codecType) { 136 this(downlinkCallQualityLevel, uplinkCallQualityLevel, callDuration, 137 numRtpPacketsTransmitted, numRtpPacketsReceived, numRtpPacketsTransmittedLost, 138 numRtpPacketsNotReceived, averageRelativeJitter, maxRelativeJitter, 139 averageRoundTripTime, codecType, false, false, false); 140 } 141 142 /** 143 * Constructor. 144 * 145 * @param callQualityLevel the call quality level (see #CallQualityLevel) 146 * @param callDuration the call duration in milliseconds 147 * @param numRtpPacketsTransmitted RTP packets sent to network 148 * @param numRtpPacketsReceived RTP packets received from network 149 * @param numRtpPacketsTransmittedLost RTP packets which were lost in network and never 150 * transmitted 151 * @param numRtpPacketsNotReceived RTP packets which were lost in network and never received 152 * @param averageRelativeJitter average relative jitter in milliseconds 153 * @param maxRelativeJitter maximum relative jitter in milliseconds 154 * @param averageRoundTripTime average round trip delay in milliseconds 155 * @param codecType the codec type 156 * @param rtpInactivityDetected True if no incoming RTP is received for a continuous duration of 157 * 4 seconds 158 * @param rxSilenceDetected True if only silence RTP packets are received for 20 seconds 159 * immediately after call is connected 160 * @param txSilenceDetected True if only silence RTP packets are sent for 20 seconds immediately 161 * after call is connected 162 */ CallQuality( @allQualityLevel int downlinkCallQualityLevel, @CallQualityLevel int uplinkCallQualityLevel, int callDuration, int numRtpPacketsTransmitted, int numRtpPacketsReceived, int numRtpPacketsTransmittedLost, int numRtpPacketsNotReceived, int averageRelativeJitter, int maxRelativeJitter, int averageRoundTripTime, int codecType, boolean rtpInactivityDetected, boolean rxSilenceDetected, boolean txSilenceDetected)163 public CallQuality( 164 @CallQualityLevel int downlinkCallQualityLevel, 165 @CallQualityLevel int uplinkCallQualityLevel, 166 int callDuration, 167 int numRtpPacketsTransmitted, 168 int numRtpPacketsReceived, 169 int numRtpPacketsTransmittedLost, 170 int numRtpPacketsNotReceived, 171 int averageRelativeJitter, 172 int maxRelativeJitter, 173 int averageRoundTripTime, 174 int codecType, 175 boolean rtpInactivityDetected, 176 boolean rxSilenceDetected, 177 boolean txSilenceDetected) { 178 this.mDownlinkCallQualityLevel = downlinkCallQualityLevel; 179 this.mUplinkCallQualityLevel = uplinkCallQualityLevel; 180 this.mCallDuration = callDuration; 181 this.mNumRtpPacketsTransmitted = numRtpPacketsTransmitted; 182 this.mNumRtpPacketsReceived = numRtpPacketsReceived; 183 this.mNumRtpPacketsTransmittedLost = numRtpPacketsTransmittedLost; 184 this.mNumRtpPacketsNotReceived = numRtpPacketsNotReceived; 185 this.mAverageRelativeJitter = averageRelativeJitter; 186 this.mMaxRelativeJitter = maxRelativeJitter; 187 this.mAverageRoundTripTime = averageRoundTripTime; 188 this.mCodecType = codecType; 189 this.mRtpInactivityDetected = rtpInactivityDetected; 190 this.mRxSilenceDetected = rxSilenceDetected; 191 this.mTxSilenceDetected = txSilenceDetected; 192 } 193 194 // getters 195 /** 196 * Returns the downlink CallQualityLevel for a given ongoing call. 197 */ 198 @CallQualityLevel getDownlinkCallQualityLevel()199 public int getDownlinkCallQualityLevel() { 200 return mDownlinkCallQualityLevel; 201 } 202 203 /** 204 * Returns the uplink CallQualityLevel for a given ongoing call. 205 */ 206 @CallQualityLevel getUplinkCallQualityLevel()207 public int getUplinkCallQualityLevel() { 208 return mUplinkCallQualityLevel; 209 } 210 211 /** 212 * Returns the duration of the call, in milliseconds. 213 */ getCallDuration()214 public int getCallDuration() { 215 return mCallDuration; 216 } 217 218 /** 219 * Returns the total number of RTP packets transmitted by this device for a given ongoing call. 220 */ getNumRtpPacketsTransmitted()221 public int getNumRtpPacketsTransmitted() { 222 return mNumRtpPacketsTransmitted; 223 } 224 225 /** 226 * Returns the total number of RTP packets received by this device for a given ongoing call. 227 */ getNumRtpPacketsReceived()228 public int getNumRtpPacketsReceived() { 229 return mNumRtpPacketsReceived; 230 } 231 232 /** 233 * Returns the number of RTP packets which were sent by this device but were lost in the 234 * network before reaching the other party. 235 */ getNumRtpPacketsTransmittedLost()236 public int getNumRtpPacketsTransmittedLost() { 237 return mNumRtpPacketsTransmittedLost; 238 } 239 240 /** 241 * Returns the number of RTP packets which were sent by the other party but were lost in the 242 * network before reaching this device. 243 */ getNumRtpPacketsNotReceived()244 public int getNumRtpPacketsNotReceived() { 245 return mNumRtpPacketsNotReceived; 246 } 247 248 /** 249 * Returns the average relative jitter in milliseconds. Jitter represents the amount of variance 250 * in interarrival time of packets, for example, if two packets are sent 2 milliseconds apart 251 * but received 3 milliseconds apart, the relative jitter between those packets is 1 252 * millisecond. 253 * 254 * <p>See RFC 3550 for more information on jitter calculations. 255 */ getAverageRelativeJitter()256 public int getAverageRelativeJitter() { 257 return mAverageRelativeJitter; 258 } 259 260 /** 261 * Returns the maximum relative jitter for a given ongoing call. Jitter represents the amount of 262 * variance in interarrival time of packets, for example, if two packets are sent 2 milliseconds 263 * apart but received 3 milliseconds apart, the relative jitter between those packets is 1 264 * millisecond. 265 * 266 * <p>See RFC 3550 for more information on jitter calculations. 267 */ getMaxRelativeJitter()268 public int getMaxRelativeJitter() { 269 return mMaxRelativeJitter; 270 } 271 272 /** 273 * Returns the average round trip time in milliseconds. 274 */ getAverageRoundTripTime()275 public int getAverageRoundTripTime() { 276 return mAverageRoundTripTime; 277 } 278 279 /** 280 * Returns true if no rtp packets are received continuously for the last 4 seconds 281 */ isRtpInactivityDetected()282 public boolean isRtpInactivityDetected() { 283 return mRtpInactivityDetected; 284 } 285 286 /** 287 * Returns true if only silence rtp packets are received for a duration of 20 seconds starting 288 * at call setup 289 */ isIncomingSilenceDetected()290 public boolean isIncomingSilenceDetected() { 291 return mRxSilenceDetected; 292 } 293 294 /** 295 * Returns true if only silence rtp packets are sent for a duration of 20 seconds starting at 296 * call setup 297 */ isOutgoingSilenceDetected()298 public boolean isOutgoingSilenceDetected() { 299 return mTxSilenceDetected; 300 } 301 302 /** 303 * Returns the codec type. This value corresponds to the AUDIO_QUALITY_* constants in 304 * {@link ImsStreamMediaProfile}. 305 * 306 * @see ImsStreamMediaProfile#AUDIO_QUALITY_NONE 307 * @see ImsStreamMediaProfile#AUDIO_QUALITY_AMR 308 * @see ImsStreamMediaProfile#AUDIO_QUALITY_AMR_WB 309 * @see ImsStreamMediaProfile#AUDIO_QUALITY_QCELP13K 310 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVRC 311 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVRC_B 312 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVRC_WB 313 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVRC_NW 314 * @see ImsStreamMediaProfile#AUDIO_QUALITY_GSM_EFR 315 * @see ImsStreamMediaProfile#AUDIO_QUALITY_GSM_FR 316 * @see ImsStreamMediaProfile#AUDIO_QUALITY_GSM_HR 317 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G711U 318 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G723 319 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G711A 320 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G722 321 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G711AB 322 * @see ImsStreamMediaProfile#AUDIO_QUALITY_G729 323 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVS_NB 324 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVS_WB 325 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVS_SWB 326 * @see ImsStreamMediaProfile#AUDIO_QUALITY_EVS_FB 327 */ getCodecType()328 public int getCodecType() { 329 return mCodecType; 330 } 331 332 // Parcelable things 333 @NonNull 334 @Override toString()335 public String toString() { 336 return "CallQuality: {downlinkCallQualityLevel=" + mDownlinkCallQualityLevel 337 + " uplinkCallQualityLevel=" + mUplinkCallQualityLevel 338 + " callDuration=" + mCallDuration 339 + " numRtpPacketsTransmitted=" + mNumRtpPacketsTransmitted 340 + " numRtpPacketsReceived=" + mNumRtpPacketsReceived 341 + " numRtpPacketsTransmittedLost=" + mNumRtpPacketsTransmittedLost 342 + " numRtpPacketsNotReceived=" + mNumRtpPacketsNotReceived 343 + " averageRelativeJitter=" + mAverageRelativeJitter 344 + " maxRelativeJitter=" + mMaxRelativeJitter 345 + " averageRoundTripTime=" + mAverageRoundTripTime 346 + " codecType=" + mCodecType 347 + " rtpInactivityDetected=" + mRtpInactivityDetected 348 + " txSilenceDetected=" + mRxSilenceDetected 349 + " rxSilenceDetected=" + mTxSilenceDetected 350 + "}"; 351 } 352 353 @Override hashCode()354 public int hashCode() { 355 return Objects.hash( 356 mDownlinkCallQualityLevel, 357 mUplinkCallQualityLevel, 358 mCallDuration, 359 mNumRtpPacketsTransmitted, 360 mNumRtpPacketsReceived, 361 mNumRtpPacketsTransmittedLost, 362 mNumRtpPacketsNotReceived, 363 mAverageRelativeJitter, 364 mMaxRelativeJitter, 365 mAverageRoundTripTime, 366 mCodecType, 367 mRtpInactivityDetected, 368 mRxSilenceDetected, 369 mTxSilenceDetected); 370 } 371 372 @Override equals(@ullable Object o)373 public boolean equals(@Nullable Object o) { 374 if (o == null || !(o instanceof CallQuality) || hashCode() != o.hashCode()) { 375 return false; 376 } 377 378 if (this == o) { 379 return true; 380 } 381 382 CallQuality s = (CallQuality) o; 383 384 return (mDownlinkCallQualityLevel == s.mDownlinkCallQualityLevel 385 && mUplinkCallQualityLevel == s.mUplinkCallQualityLevel 386 && mCallDuration == s.mCallDuration 387 && mNumRtpPacketsTransmitted == s.mNumRtpPacketsTransmitted 388 && mNumRtpPacketsReceived == s.mNumRtpPacketsReceived 389 && mNumRtpPacketsTransmittedLost == s.mNumRtpPacketsTransmittedLost 390 && mNumRtpPacketsNotReceived == s.mNumRtpPacketsNotReceived 391 && mAverageRelativeJitter == s.mAverageRelativeJitter 392 && mMaxRelativeJitter == s.mMaxRelativeJitter 393 && mAverageRoundTripTime == s.mAverageRoundTripTime 394 && mCodecType == s.mCodecType 395 && mRtpInactivityDetected == s.mRtpInactivityDetected 396 && mRxSilenceDetected == s.mRxSilenceDetected 397 && mTxSilenceDetected == s.mTxSilenceDetected); 398 } 399 400 /** 401 * {@link Parcelable#describeContents} 402 */ describeContents()403 public @Parcelable.ContentsFlags int describeContents() { 404 return 0; 405 } 406 407 /** 408 * {@link Parcelable#writeToParcel} 409 */ writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags)410 public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) { 411 dest.writeInt(mDownlinkCallQualityLevel); 412 dest.writeInt(mUplinkCallQualityLevel); 413 dest.writeInt(mCallDuration); 414 dest.writeInt(mNumRtpPacketsTransmitted); 415 dest.writeInt(mNumRtpPacketsReceived); 416 dest.writeInt(mNumRtpPacketsTransmittedLost); 417 dest.writeInt(mNumRtpPacketsNotReceived); 418 dest.writeInt(mAverageRelativeJitter); 419 dest.writeInt(mMaxRelativeJitter); 420 dest.writeInt(mAverageRoundTripTime); 421 dest.writeInt(mCodecType); 422 dest.writeBoolean(mRtpInactivityDetected); 423 dest.writeBoolean(mRxSilenceDetected); 424 dest.writeBoolean(mTxSilenceDetected); 425 } 426 427 public static final @android.annotation.NonNull Parcelable.Creator<CallQuality> CREATOR = new Parcelable.Creator() { 428 public CallQuality createFromParcel(Parcel in) { 429 return new CallQuality(in); 430 } 431 432 public CallQuality[] newArray(int size) { 433 return new CallQuality[size]; 434 } 435 }; 436 } 437