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