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