1 /* 2 * Copyright (C) 2019 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 com.android.internal.telephony.metrics; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.mockito.Mockito.when; 21 22 import android.telephony.CallQuality; 23 import android.telephony.CellSignalStrengthCdma; 24 import android.telephony.CellSignalStrengthGsm; 25 import android.telephony.CellSignalStrengthLte; 26 import android.telephony.CellSignalStrengthNr; 27 import android.telephony.CellSignalStrengthTdscdma; 28 import android.telephony.CellSignalStrengthWcdma; 29 import android.telephony.SignalStrength; 30 31 import com.android.internal.telephony.TelephonyTest; 32 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.CallQualitySummary; 33 34 import org.junit.After; 35 import org.junit.Before; 36 import org.junit.Test; 37 38 public class CallQualityMetricsTest extends TelephonyTest { 39 40 private CallQualityMetrics mCallQualityMetrics; 41 42 @Before setUp()43 public void setUp() throws Exception { 44 super.setUp(getClass().getSimpleName()); 45 mCallQualityMetrics = new CallQualityMetrics(mPhone); 46 47 // the ImsPhone does not return a ServiceStateTracker, so CallQualityMetrics gets the 48 // default phone from the ImsPhone and uses that to get the ServiceStateTracker, therefore 49 // we need to mock the default phone as well. 50 when(mPhone.getDefaultPhone()).thenReturn(mPhone); 51 } 52 53 @After tearDown()54 public void tearDown() throws Exception { 55 super.tearDown(); 56 } 57 constructCallQuality(int dlQuality, int ulQuality, int durationMs)58 private CallQuality constructCallQuality(int dlQuality, int ulQuality, int durationMs) { 59 return new CallQuality( 60 dlQuality, 61 ulQuality, 62 durationMs, 63 0, 0, 0, 0, 0, 0, 0, 0); // packets, jitter and codec (okay to ignore for testing) 64 } 65 66 /** 67 * Verify that good/bad quality and total duration stats are correct. 68 */ 69 @Test testTotalDurations()70 public void testTotalDurations() { 71 // Call quality in the following sequence: 72 // 73 // DL: GOOD GOOD BAD 74 // UL: GOOD BAD GOOD 75 // |----------|----------|--------| 76 // 0 5 10 14 77 // 78 // 0s = Start of call. Assumed to be good quality 79 // 5s = Switches to UL bad quality 80 // 10s = Switches to UL good quality, DL bad quality 81 // 14s = End of call. Switches to UL bad quality, DL good quality 82 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 83 CallQuality.CALL_QUALITY_BAD, 5000); 84 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 85 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 86 CallQuality cq3 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 87 CallQuality.CALL_QUALITY_BAD, 14000); 88 89 mCallQualityMetrics.saveCallQuality(cq1); 90 mCallQualityMetrics.saveCallQuality(cq2); 91 mCallQualityMetrics.saveCallQuality(cq3); 92 93 // verify UL quality durations 94 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 95 assertEquals(9, dlSummary.totalGoodQualityDurationInSeconds); 96 assertEquals(5, dlSummary.totalBadQualityDurationInSeconds); 97 assertEquals(14, dlSummary.totalDurationWithQualityInformationInSeconds); 98 99 // verify DL quality durations 100 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 101 assertEquals(5, ulSummary.totalGoodQualityDurationInSeconds); 102 assertEquals(9, ulSummary.totalBadQualityDurationInSeconds); 103 assertEquals(14, ulSummary.totalDurationWithQualityInformationInSeconds); 104 } 105 106 /** 107 * Verify that good/bad quality and total duration stats are correct. 108 * 109 * Similar to testTotalDurations, but getCallQualitySummaryUl/Dl will be called multiple times, 110 * so verify that it continues to work after the first call. 111 */ 112 @Test testTotalDurations_MultipleChecks()113 public void testTotalDurations_MultipleChecks() { 114 // Call quality in the following sequence: 115 // 116 // DL: GOOD GOOD BAD 117 // UL: GOOD BAD GOOD 118 // |----------|----------|--------| 119 // 0 5 10 14 120 // 121 // 0s = Start of call. Assumed to be good quality 122 // 5s = Switches to UL bad quality 123 // 10s = Switches to UL good quality, DL bad quality 124 // 14s = End of call. Switches to UL bad quality, DL good quality 125 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 126 CallQuality.CALL_QUALITY_BAD, 5000); 127 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 128 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 129 CallQuality cq3 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 130 CallQuality.CALL_QUALITY_BAD, 14000); 131 132 mCallQualityMetrics.saveCallQuality(cq1); 133 mCallQualityMetrics.saveCallQuality(cq2); 134 mCallQualityMetrics.saveCallQuality(cq3); 135 136 // verify UL quality durations 137 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 138 assertEquals(9, dlSummary.totalGoodQualityDurationInSeconds); 139 assertEquals(5, dlSummary.totalBadQualityDurationInSeconds); 140 assertEquals(14, dlSummary.totalDurationWithQualityInformationInSeconds); 141 142 // verify DL quality durations 143 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 144 assertEquals(5, ulSummary.totalGoodQualityDurationInSeconds); 145 assertEquals(9, ulSummary.totalBadQualityDurationInSeconds); 146 assertEquals(14, ulSummary.totalDurationWithQualityInformationInSeconds); 147 148 // verify UL quality durations 149 dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 150 assertEquals(9, dlSummary.totalGoodQualityDurationInSeconds); 151 assertEquals(5, dlSummary.totalBadQualityDurationInSeconds); 152 assertEquals(14, dlSummary.totalDurationWithQualityInformationInSeconds); 153 154 // verify DL quality durations 155 ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 156 assertEquals(5, ulSummary.totalGoodQualityDurationInSeconds); 157 assertEquals(9, ulSummary.totalBadQualityDurationInSeconds); 158 assertEquals(14, ulSummary.totalDurationWithQualityInformationInSeconds); 159 } 160 161 162 /** 163 * Verify that good/bad quality and total duration stats are correct. 164 * 165 * Similar to testTotalDurations but we report the call quality out of order. 166 */ 167 @Test testTotalDurations_ReportedOutOfOrder()168 public void testTotalDurations_ReportedOutOfOrder() { 169 // Call quality in the following sequence: 170 // 171 // DL: GOOD GOOD BAD 172 // UL: GOOD BAD GOOD 173 // |----------|----------|--------| 174 // 0 5 10 14 175 // 176 // 0s = Start of call. Assumed to be good quality 177 // 5s = Switches to UL bad quality 178 // 10s = Switches to UL good quality, DL bad quality 179 // 14s = End of call. Switches to UL bad quality, DL good quality 180 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 181 CallQuality.CALL_QUALITY_BAD, 5000); 182 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 183 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 184 CallQuality cq3 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 185 CallQuality.CALL_QUALITY_BAD, 14000); 186 187 mCallQualityMetrics.saveCallQuality(cq1); 188 mCallQualityMetrics.saveCallQuality(cq3); 189 mCallQualityMetrics.saveCallQuality(cq2); 190 191 // verify UL quality durations 192 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 193 assertEquals(9, dlSummary.totalGoodQualityDurationInSeconds); 194 assertEquals(5, dlSummary.totalBadQualityDurationInSeconds); 195 assertEquals(14, dlSummary.totalDurationWithQualityInformationInSeconds); 196 197 // verify DL quality durations 198 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 199 assertEquals(5, ulSummary.totalGoodQualityDurationInSeconds); 200 assertEquals(9, ulSummary.totalBadQualityDurationInSeconds); 201 assertEquals(14, ulSummary.totalDurationWithQualityInformationInSeconds); 202 } 203 204 /** 205 * Verify that a new CallQualityMetrics object is able to return empty summaries if no 206 * CallQuality is reported for the duration of a call. 207 */ 208 @Test testNoQualityReported()209 public void testNoQualityReported() { 210 // getting the summary for a new CallQualityMetrics object should not fail, and all 211 // durations should be 0 212 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 213 assertEquals(0, dlSummary.totalGoodQualityDurationInSeconds); 214 assertEquals(0, dlSummary.totalBadQualityDurationInSeconds); 215 assertEquals(0, dlSummary.totalDurationWithQualityInformationInSeconds); 216 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 217 assertEquals(0, ulSummary.totalGoodQualityDurationInSeconds); 218 assertEquals(0, ulSummary.totalBadQualityDurationInSeconds); 219 assertEquals(0, ulSummary.totalDurationWithQualityInformationInSeconds); 220 } 221 222 /** 223 * Verify that if either UL or DL call quality level is not available, the CallQuality update is 224 * ignored. 225 */ 226 @Test testNotAvailableIsIgnored()227 public void testNotAvailableIsIgnored() { 228 // CallQuality updates from the IMS service with CALL_QUALITY_NOT_AVAILABLE should be 229 // ignored 230 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_NOT_AVAILABLE, 231 CallQuality.CALL_QUALITY_BAD, 5000); 232 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 233 CallQuality.CALL_QUALITY_NOT_AVAILABLE, 10000); 234 mCallQualityMetrics.saveCallQuality(cq1); 235 mCallQualityMetrics.saveCallQuality(cq2); 236 237 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 238 assertEquals(0, dlSummary.totalGoodQualityDurationInSeconds); 239 assertEquals(0, dlSummary.totalBadQualityDurationInSeconds); 240 assertEquals(0, dlSummary.totalDurationWithQualityInformationInSeconds); 241 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 242 assertEquals(0, ulSummary.totalGoodQualityDurationInSeconds); 243 assertEquals(0, ulSummary.totalBadQualityDurationInSeconds); 244 assertEquals(0, ulSummary.totalDurationWithQualityInformationInSeconds); 245 } 246 247 /** 248 * Test that the best and worst SignalStrength (currently just LTE RSSNR) is correctly kept 249 * track of. CallQualityMetrics should log the best and worst SS for good and bad quality, but 250 * this just tests for good quality since the logic is the same. 251 */ 252 @Test testBestAndWorstSs()253 public void testBestAndWorstSs() { 254 // save good quality with high rssnr 255 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 256 CallQuality.CALL_QUALITY_EXCELLENT, 5000); 257 int rssnr1 = 30; 258 // ignore everything except rssnr 259 CellSignalStrengthLte lteSs1 = new CellSignalStrengthLte(0, 0, 0, rssnr1, 0, 0); 260 SignalStrength ss1 = new SignalStrength( 261 new CellSignalStrengthCdma(), 262 new CellSignalStrengthGsm(), 263 new CellSignalStrengthWcdma(), 264 new CellSignalStrengthTdscdma(), 265 lteSs1, 266 new CellSignalStrengthNr()); 267 when(mSST.getSignalStrength()).thenReturn(ss1); 268 mCallQualityMetrics.saveCallQuality(cq1); 269 270 // save good quality with low rssnr 271 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 272 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 273 int rssnr2 = -20; 274 // ignore everything except rssnr 275 CellSignalStrengthLte lteSs2 = new CellSignalStrengthLte(0, 0, 0, rssnr2, 0, 0); 276 SignalStrength ss2 = new SignalStrength( 277 new CellSignalStrengthCdma(), 278 new CellSignalStrengthGsm(), 279 new CellSignalStrengthWcdma(), 280 new CellSignalStrengthTdscdma(), 281 lteSs2, 282 new CellSignalStrengthNr()); 283 when(mSST.getSignalStrength()).thenReturn(ss2); 284 mCallQualityMetrics.saveCallQuality(cq1); 285 286 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 287 assertEquals(rssnr1, dlSummary.bestSsWithGoodQuality.lteSnr); 288 assertEquals(rssnr2, dlSummary.worstSsWithGoodQuality.lteSnr); 289 } 290 291 /** 292 * Verifies that the snapshot of the end (the last reported call quality) is correct. 293 * Currently this just checks the duration since the logic is all the same and it doesn't seem 294 * likely that one field would be preserved and others would be lost. 295 */ 296 @Test testSnapshotOfEndDuration()297 public void testSnapshotOfEndDuration() { 298 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 299 CallQuality.CALL_QUALITY_BAD, 5000); 300 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 301 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 302 CallQuality cq3 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 303 CallQuality.CALL_QUALITY_BAD, 14000); 304 305 mCallQualityMetrics.saveCallQuality(cq1); 306 mCallQualityMetrics.saveCallQuality(cq2); 307 mCallQualityMetrics.saveCallQuality(cq3); 308 309 // verify snapshot of end 310 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 311 assertEquals(14, dlSummary.snapshotOfEnd.durationInSeconds); 312 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 313 assertEquals(14, ulSummary.snapshotOfEnd.durationInSeconds); 314 } 315 316 /** 317 * Verifies that the snapshot of the end (the last reported call quality) is correct. 318 * Currently this just checks the duration since the logic is all the same and it doesn't seem 319 * likely that one field would be preserved and others would be lost. 320 * 321 * Similar to testSnapshotOfEndDuration but we report the call quality out of order 322 */ 323 @Test testSnapshotOfEndDuration_ReportedOutOfOrder()324 public void testSnapshotOfEndDuration_ReportedOutOfOrder() { 325 CallQuality cq1 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 326 CallQuality.CALL_QUALITY_BAD, 5000); 327 CallQuality cq2 = constructCallQuality(CallQuality.CALL_QUALITY_BAD, 328 CallQuality.CALL_QUALITY_EXCELLENT, 10000); 329 CallQuality cq3 = constructCallQuality(CallQuality.CALL_QUALITY_EXCELLENT, 330 CallQuality.CALL_QUALITY_BAD, 14000); 331 332 mCallQualityMetrics.saveCallQuality(cq1); 333 mCallQualityMetrics.saveCallQuality(cq3); 334 mCallQualityMetrics.saveCallQuality(cq2); 335 336 // verify snapshot of end 337 CallQualitySummary dlSummary = mCallQualityMetrics.getCallQualitySummaryDl(); 338 assertEquals(14, dlSummary.snapshotOfEnd.durationInSeconds); 339 CallQualitySummary ulSummary = mCallQualityMetrics.getCallQualitySummaryUl(); 340 assertEquals(14, ulSummary.snapshotOfEnd.durationInSeconds); 341 } 342 } 343