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 com.android.telephony.imsmedia; 18 19 import android.hardware.radio.ims.media.CodecMode; 20 import android.hardware.radio.ims.media.CodecParams; 21 import android.hardware.radio.ims.media.CodecSpecificParams; 22 import android.hardware.radio.ims.media.DtmfParams; 23 import android.hardware.radio.ims.media.RtpAddress; 24 import android.hardware.radio.ims.media.RtpSessionParams; 25 import android.net.InetAddresses; 26 import android.os.Handler; 27 import android.os.Message; 28 import android.os.ParcelFileDescriptor; 29 import android.telephony.CallQuality; 30 import android.telephony.ims.RtpHeaderExtension; 31 import android.telephony.imsmedia.AmrParams; 32 import android.telephony.imsmedia.AnbrMode; 33 import android.telephony.imsmedia.AudioConfig; 34 import android.telephony.imsmedia.EvsParams; 35 import android.telephony.imsmedia.MediaQualityStatus; 36 import android.telephony.imsmedia.MediaQualityThreshold; 37 import android.telephony.imsmedia.RtcpConfig; 38 import android.telephony.imsmedia.RtpConfig; 39 40 import com.android.telephony.imsmedia.ImsMediaController.OpenSessionCallback; 41 42 import java.net.InetSocketAddress; 43 import java.util.Arrays; 44 45 /** 46 * Class consists of utility methods and sub classes 47 * 48 * @hide 49 */ 50 public final class Utils { 51 52 static final int UNUSED = -1; 53 54 /** Class to encapsulate open session parameters */ 55 static final class OpenSessionParams { 56 private final ParcelFileDescriptor rtpFd; 57 private final ParcelFileDescriptor rtcpFd; 58 private final RtpConfig rtpConfig; 59 private final OpenSessionCallback callback; 60 OpenSessionParams(final ParcelFileDescriptor rtpFd, final ParcelFileDescriptor rtcpFd, final RtpConfig rtpConfig, final OpenSessionCallback callback)61 OpenSessionParams(final ParcelFileDescriptor rtpFd, 62 final ParcelFileDescriptor rtcpFd, 63 final RtpConfig rtpConfig, 64 final OpenSessionCallback callback) { 65 this.rtpFd = rtpFd; 66 this.rtcpFd = rtcpFd; 67 this.rtpConfig = rtpConfig; 68 this.callback = callback; 69 } 70 getRtpFd()71 ParcelFileDescriptor getRtpFd() { 72 return rtpFd; 73 } 74 getRtcpFd()75 ParcelFileDescriptor getRtcpFd() { 76 return rtcpFd; 77 } 78 getRtpConfig()79 RtpConfig getRtpConfig() { 80 return rtpConfig; 81 } 82 getCallback()83 OpenSessionCallback getCallback() { 84 return callback; 85 } 86 } 87 sendMessage(final Handler handler, final int command)88 static void sendMessage(final Handler handler, final int command) { 89 final Message msg = handler.obtainMessage(command); 90 msg.sendToTarget(); 91 } 92 sendMessage(final Handler handler, final int command, final Object argument)93 static void sendMessage(final Handler handler, final int command, final Object argument) { 94 final Message msg = handler.obtainMessage(command, argument); 95 msg.sendToTarget(); 96 } 97 sendMessage(final Handler handler, final int command, final int arg1, final int arg2)98 static void sendMessage(final Handler handler, 99 final int command, final int arg1, final int arg2) { 100 final Message msg = handler.obtainMessage(command, arg1, arg2); 101 msg.sendToTarget(); 102 } 103 sendMessage(final Handler handler, final int command, final int arg1, final int arg2, final Object object)104 static void sendMessage(final Handler handler, final int command, 105 final int arg1, final int arg2, final Object object) { 106 final Message msg = handler.obtainMessage(command, arg1, arg2, object); 107 msg.sendToTarget(); 108 } 109 buildRtpAddress(final AudioConfig audioConfig)110 private static RtpAddress buildRtpAddress(final AudioConfig audioConfig) { 111 final RtpAddress addr = new RtpAddress(); 112 113 addr.ipAddress = audioConfig.getRemoteRtpAddress().getAddress().getHostAddress(); 114 addr.portNumber = audioConfig.getRemoteRtpAddress().getPort(); 115 116 return addr; 117 } 118 buildDtmfParams(final AudioConfig audioConfig)119 private static DtmfParams buildDtmfParams(final AudioConfig audioConfig) { 120 final DtmfParams dtmfParams = new DtmfParams(); 121 122 dtmfParams.txPayloadTypeNumber = audioConfig.getTxDtmfPayloadTypeNumber(); 123 dtmfParams.rxPayloadTypeNumber = audioConfig.getRxDtmfPayloadTypeNumber(); 124 dtmfParams.samplingRateKHz = audioConfig.getDtmfSamplingRateKHz(); 125 126 return dtmfParams; 127 } 128 129 private static android.hardware.radio.ims.media.AmrParams buildAmrParams(final AudioConfig audioConfig)130 buildAmrParams(final AudioConfig audioConfig) { 131 final android.hardware.radio.ims.media.AmrParams amrParams = 132 new android.hardware.radio.ims.media.AmrParams(); 133 134 amrParams.amrMode = audioConfig.getAmrParams().getAmrMode(); 135 amrParams.octetAligned = audioConfig.getAmrParams().getOctetAligned(); 136 amrParams.maxRedundancyMillis = audioConfig.getAmrParams().getMaxRedundancyMillis(); 137 138 return amrParams; 139 } 140 141 private static android.hardware.radio.ims.media.EvsParams buildEvsParams(final AudioConfig audioConfig)142 buildEvsParams(final AudioConfig audioConfig) { 143 final android.hardware.radio.ims.media.EvsParams evsParams = 144 new android.hardware.radio.ims.media.EvsParams(); 145 146 evsParams.bandwidth = audioConfig.getEvsParams().getEvsBandwidth(); 147 evsParams.evsMode = audioConfig.getEvsParams().getEvsMode(); 148 evsParams.channelAwareMode = audioConfig.getEvsParams().getChannelAwareMode(); 149 evsParams.useHeaderFullOnly = 150 audioConfig.getEvsParams().getUseHeaderFullOnly(); 151 evsParams.codecModeRequest = audioConfig.getEvsParams().getCodecModeRequest(); 152 153 return evsParams; 154 } 155 buildCodecParams(final AudioConfig audioConfig)156 private static CodecParams buildCodecParams(final AudioConfig audioConfig) { 157 final CodecParams codecParams = new CodecParams(); 158 159 codecParams.codecType = audioConfig.getCodecType(); 160 codecParams.rxPayloadTypeNumber = audioConfig.getRxPayloadTypeNumber(); 161 codecParams.txPayloadTypeNumber = audioConfig.getTxPayloadTypeNumber(); 162 codecParams.samplingRateKHz = audioConfig.getSamplingRateKHz(); 163 codecParams.dtxEnabled = audioConfig.getDtxEnabled(); 164 165 if (audioConfig.getCodecType() == AudioConfig.CODEC_AMR 166 || audioConfig.getCodecType() == AudioConfig.CODEC_AMR_WB) { 167 codecParams.codecSpecificParams = new CodecSpecificParams(); 168 codecParams.codecSpecificParams.setAmr(buildAmrParams(audioConfig)); 169 } else if (audioConfig.getCodecType() == AudioConfig.CODEC_EVS) { 170 codecParams.codecSpecificParams = new CodecSpecificParams(); 171 codecParams.codecSpecificParams.setEvs(buildEvsParams(audioConfig)); 172 } 173 174 return codecParams; 175 } 176 177 private static android.hardware.radio.ims.media.AnbrMode buildAnbrMode(final AudioConfig audioConfig)178 buildAnbrMode(final AudioConfig audioConfig) { 179 final android.hardware.radio.ims.media.AnbrMode anbrModeParams = 180 new android.hardware.radio.ims.media.AnbrMode(); 181 if (audioConfig.getAnbrMode() == null) { 182 return null; 183 } else { 184 if (audioConfig.getCodecType() == AudioConfig.CODEC_AMR 185 || audioConfig.getCodecType() == AudioConfig.CODEC_AMR_WB) { 186 anbrModeParams.anbrUplinkMode = new CodecMode(); 187 anbrModeParams.anbrDownlinkMode = new CodecMode(); 188 189 anbrModeParams.anbrUplinkMode.setAmr( 190 audioConfig.getAnbrMode().getAnbrUplinkCodecMode()); 191 anbrModeParams.anbrDownlinkMode.setAmr( 192 audioConfig.getAnbrMode().getAnbrDownlinkCodecMode()); 193 } else if (audioConfig.getCodecType() == AudioConfig.CODEC_EVS) { 194 anbrModeParams.anbrUplinkMode = new CodecMode(); 195 anbrModeParams.anbrDownlinkMode = new CodecMode(); 196 197 anbrModeParams.anbrUplinkMode.setEvs( 198 audioConfig.getAnbrMode().getAnbrUplinkCodecMode()); 199 anbrModeParams.anbrDownlinkMode.setEvs( 200 audioConfig.getAnbrMode().getAnbrDownlinkCodecMode()); 201 } 202 203 return anbrModeParams; 204 } 205 } 206 buildSessionParams(final AudioConfig audioConfig)207 private static RtpSessionParams buildSessionParams(final AudioConfig audioConfig) { 208 final RtpSessionParams sessionParams = new RtpSessionParams(); 209 210 sessionParams.pTimeMillis = audioConfig.getPtimeMillis(); 211 sessionParams.maxPtimeMillis = audioConfig.getMaxPtimeMillis(); 212 sessionParams.dscp = audioConfig.getDscp(); 213 sessionParams.dtmfParams = buildDtmfParams(audioConfig); 214 sessionParams.codecParams = buildCodecParams(audioConfig); 215 216 return sessionParams; 217 } 218 219 private static android.hardware.radio.ims.media.RtcpConfig buildRtcpConfig(final AudioConfig audioConfig)220 buildRtcpConfig(final AudioConfig audioConfig) { 221 final android.hardware.radio.ims.media.RtcpConfig rtcpConfig = 222 new android.hardware.radio.ims.media.RtcpConfig(); 223 224 rtcpConfig.canonicalName = audioConfig.getRtcpConfig().getCanonicalName(); 225 rtcpConfig.transmitPort = audioConfig.getRtcpConfig().getTransmitPort(); 226 rtcpConfig.transmitIntervalSec = audioConfig.getRtcpConfig().getIntervalSec(); 227 rtcpConfig.rtcpXrBlocks = audioConfig.getRtcpConfig().getRtcpXrBlockTypes(); 228 229 return rtcpConfig; 230 } 231 232 /** Converts {@link AudioConfig} to HAL RtpConfig */ convertToRtpConfig( final AudioConfig audioConfig)233 public static android.hardware.radio.ims.media.RtpConfig convertToRtpConfig( 234 final AudioConfig audioConfig) { 235 final android.hardware.radio.ims.media.RtpConfig rtpConfig; 236 237 if (audioConfig == null) { 238 rtpConfig = null; 239 } else { 240 rtpConfig = new android.hardware.radio.ims.media.RtpConfig(); 241 rtpConfig.direction = audioConfig.getMediaDirection(); 242 rtpConfig.accessNetwork = audioConfig.getAccessNetwork(); 243 rtpConfig.remoteAddress = buildRtpAddress(audioConfig); 244 rtpConfig.sessionParams = buildSessionParams(audioConfig); 245 rtpConfig.rtcpConfig = buildRtcpConfig(audioConfig); 246 rtpConfig.anbrModeParams = buildAnbrMode(audioConfig); 247 } 248 249 return rtpConfig; 250 } 251 252 /** Converts {@link MediaQuailtyStatus} to HAL MediaQuailtyStatus */ 253 public static android.hardware.radio.ims.media.MediaQualityStatus convertToHalMediaQualityStatus(final MediaQualityStatus status)254 convertToHalMediaQualityStatus(final MediaQualityStatus status) { 255 final android.hardware.radio.ims.media.MediaQualityStatus halStatus = 256 new android.hardware.radio.ims.media.MediaQualityStatus(); 257 halStatus.rtpInactivityTimeMillis = status.getRtpInactivityTimeMillis(); 258 halStatus.rtcpInactivityTimeMillis = status.getRtcpInactivityTimeMillis(); 259 halStatus.rtpPacketLossRate = status.getRtpPacketLossRate(); 260 halStatus.rtpJitterMillis = status.getRtpJitterMillis(); 261 return halStatus; 262 } 263 buildRtcpConfig( final android.hardware.radio.ims.media.RtpConfig rtpConfig)264 private static RtcpConfig buildRtcpConfig( 265 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 266 final RtcpConfig rtcpConfig; 267 268 if (rtpConfig.rtcpConfig == null) { 269 rtcpConfig = null; 270 } else { 271 rtcpConfig = new RtcpConfig.Builder() 272 .setCanonicalName(rtpConfig.rtcpConfig.canonicalName) 273 .setTransmitPort(rtpConfig.rtcpConfig.transmitPort) 274 .setIntervalSec(rtpConfig.rtcpConfig.transmitIntervalSec) 275 .setRtcpXrBlockTypes(rtpConfig.rtcpConfig.rtcpXrBlocks) 276 .build(); 277 } 278 279 return rtcpConfig; 280 } 281 buildEvsParams( final android.hardware.radio.ims.media.RtpConfig rtpConfig)282 private static EvsParams buildEvsParams( 283 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 284 final EvsParams evsParams; 285 286 if (rtpConfig == null 287 || rtpConfig.sessionParams == null 288 || rtpConfig.sessionParams.codecParams == null 289 || rtpConfig.sessionParams.codecParams.codecSpecificParams == null 290 || rtpConfig.sessionParams.codecParams.codecSpecificParams.getTag() 291 != CodecSpecificParams.evs) { 292 evsParams = null; 293 } else { 294 final android.hardware.radio.ims.media.EvsParams evs = 295 rtpConfig.sessionParams.codecParams.codecSpecificParams.getEvs(); 296 evsParams = new EvsParams.Builder() 297 .setEvsbandwidth(evs.bandwidth) 298 .setEvsMode(evs.evsMode) 299 .setChannelAwareMode(evs.channelAwareMode) 300 .setHeaderFullOnly(evs.useHeaderFullOnly) 301 .setCodecModeRequest(evs.codecModeRequest) 302 .build(); 303 } 304 305 return evsParams; 306 } 307 buildAmrParams( final android.hardware.radio.ims.media.RtpConfig rtpConfig)308 private static AmrParams buildAmrParams( 309 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 310 final AmrParams amrParams; 311 312 if (rtpConfig == null 313 || rtpConfig.sessionParams == null 314 || rtpConfig.sessionParams.codecParams == null 315 || rtpConfig.sessionParams.codecParams.codecSpecificParams == null 316 || rtpConfig.sessionParams.codecParams.codecSpecificParams.getTag() 317 != CodecSpecificParams.amr) { 318 amrParams = null; 319 } else { 320 final android.hardware.radio.ims.media.AmrParams amr = 321 rtpConfig.sessionParams.codecParams.codecSpecificParams.getAmr(); 322 amrParams = new AmrParams.Builder() 323 .setAmrMode(amr.amrMode) 324 .setOctetAligned(amr.octetAligned) 325 .setMaxRedundancyMillis(amr.maxRedundancyMillis) 326 .build(); 327 } 328 329 return amrParams; 330 } 331 buildAnbrMode( final android.hardware.radio.ims.media.RtpConfig rtpConfig)332 private static AnbrMode buildAnbrMode( 333 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 334 final AnbrMode anbrMode; 335 336 if (rtpConfig == null 337 || rtpConfig.sessionParams == null 338 || rtpConfig.sessionParams.codecParams == null) { 339 anbrMode = null; 340 } else { 341 if (rtpConfig.sessionParams.codecParams.codecType == AudioConfig.CODEC_EVS) { 342 anbrMode = new AnbrMode.Builder() 343 .setAnbrUplinkCodecMode(rtpConfig.anbrModeParams.anbrUplinkMode.getEvs()) 344 .setAnbrDownlinkCodecMode( 345 rtpConfig.anbrModeParams.anbrDownlinkMode.getEvs()) 346 .build(); 347 } else if (rtpConfig.sessionParams.codecParams.codecType == AudioConfig.CODEC_AMR 348 || rtpConfig.sessionParams.codecParams.codecType == AudioConfig.CODEC_AMR_WB) { 349 anbrMode = new AnbrMode.Builder() 350 .setAnbrUplinkCodecMode(rtpConfig.anbrModeParams.anbrUplinkMode.getAmr()) 351 .setAnbrDownlinkCodecMode( 352 rtpConfig.anbrModeParams.anbrDownlinkMode.getAmr()) 353 .build(); 354 } else { 355 anbrMode = new AnbrMode.Builder() 356 .setAnbrUplinkCodecMode(0) 357 .setAnbrDownlinkCodecMode(0) 358 .build(); 359 } 360 } 361 362 return anbrMode; 363 } 364 buildRtpAddress( final android.hardware.radio.ims.media.RtpConfig rtpConfig)365 private static InetSocketAddress buildRtpAddress( 366 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 367 final InetSocketAddress rtpAddress; 368 369 if (rtpConfig.remoteAddress == null) { 370 rtpAddress = null; 371 } else { 372 rtpAddress = new InetSocketAddress( 373 InetAddresses.parseNumericAddress(rtpConfig.remoteAddress.ipAddress), 374 rtpConfig.remoteAddress.portNumber); 375 } 376 377 return rtpAddress; 378 } 379 380 /** Converts HAL RtpConfig to AudioConfig */ convertToAudioConfig( final android.hardware.radio.ims.media.RtpConfig rtpConfig)381 public static AudioConfig convertToAudioConfig( 382 final android.hardware.radio.ims.media.RtpConfig rtpConfig) { 383 final AudioConfig audioConfig; 384 385 if (rtpConfig == null) { 386 audioConfig = null; 387 } else { 388 audioConfig = new AudioConfig.Builder() 389 .setMediaDirection(rtpConfig.direction) 390 .setAccessNetwork(rtpConfig.accessNetwork) 391 .setRemoteRtpAddress(buildRtpAddress(rtpConfig)) 392 .setRtcpConfig(buildRtcpConfig(rtpConfig)) 393 .setEvsParams(buildEvsParams(rtpConfig)) 394 .setAmrParams(buildAmrParams(rtpConfig)) 395 .setAnbrMode(buildAnbrMode(rtpConfig)) 396 .build(); 397 398 /** Populate session related parameters if present */ 399 if (rtpConfig.sessionParams != null) { 400 audioConfig.setDscp(rtpConfig.sessionParams.dscp); 401 audioConfig.setPtimeMillis(rtpConfig.sessionParams.pTimeMillis); 402 audioConfig.setMaxPtimeMillis(rtpConfig.sessionParams.maxPtimeMillis); 403 404 /** Populate DTMF parameter */ 405 final DtmfParams dtmfParams = rtpConfig.sessionParams.dtmfParams; 406 if (dtmfParams != null) { 407 audioConfig.setTxDtmfPayloadTypeNumber(dtmfParams.txPayloadTypeNumber); 408 audioConfig.setRxDtmfPayloadTypeNumber(dtmfParams.rxPayloadTypeNumber); 409 audioConfig.setDtmfSamplingRateKHz(dtmfParams.samplingRateKHz); 410 } 411 412 /** Populate codec parameters */ 413 final CodecParams codecParams = rtpConfig.sessionParams.codecParams; 414 if (codecParams != null) { 415 audioConfig.setCodecType(codecParams.codecType); 416 audioConfig.setRxPayloadTypeNumber(codecParams.rxPayloadTypeNumber); 417 audioConfig.setTxPayloadTypeNumber(codecParams.txPayloadTypeNumber); 418 audioConfig.setSamplingRateKHz(codecParams.samplingRateKHz); 419 audioConfig.setDtxEnabled(codecParams.dtxEnabled); 420 } 421 } 422 } 423 424 return audioConfig; 425 } 426 427 /** Converts {@link MediaQualityThreshold} to HAL MediaQualityThreshold */ 428 public static android.hardware.radio.ims.media.MediaQualityThreshold convertMediaQualityThreshold(final MediaQualityThreshold in)429 convertMediaQualityThreshold(final MediaQualityThreshold in) { 430 final android.hardware.radio.ims.media.MediaQualityThreshold out; 431 432 if (in == null) { 433 out = null; 434 } else { 435 out = new android.hardware.radio.ims.media.MediaQualityThreshold(); 436 out.rtpInactivityTimerMillis = Arrays.copyOf(in.getRtpInactivityTimerMillis(), 437 in.getRtpInactivityTimerMillis().length); 438 out.rtcpInactivityTimerMillis = in.getRtcpInactivityTimerMillis(); 439 out.rtpHysteresisTimeInMillis = in.getRtpHysteresisTimeInMillis(); 440 out.rtpPacketLossDurationMillis = in.getRtpPacketLossDurationMillis(); 441 out.rtpPacketLossRate = Arrays.copyOf(in.getRtpPacketLossRate(), 442 in.getRtpPacketLossRate().length); 443 out.rtpJitterMillis = Arrays.copyOf(in.getRtpJitterMillis(), 444 in.getRtpJitterMillis().length); 445 out.notifyCurrentStatus = in.getNotifyCurrentStatus(); 446 } 447 448 return out; 449 } 450 451 /** Converts HAL MediaQualityThreshold to {@link MediaQualityThreshold} */ convertMediaQualityThreshold( final android.hardware.radio.ims.media.MediaQualityThreshold in)452 public static MediaQualityThreshold convertMediaQualityThreshold( 453 final android.hardware.radio.ims.media.MediaQualityThreshold in) { 454 return (in == null) ? null : new MediaQualityThreshold.Builder() 455 .setRtpInactivityTimerMillis(in.rtpInactivityTimerMillis) 456 .setRtcpInactivityTimerMillis(in.rtcpInactivityTimerMillis) 457 .setRtpHysteresisTimeInMillis(in.rtpHysteresisTimeInMillis) 458 .setRtpPacketLossDurationMillis(in.rtpPacketLossDurationMillis) 459 .setRtpPacketLossRate(in.rtpPacketLossRate) 460 .setRtpJitterMillis(in.rtpJitterMillis) 461 .setNotifyCurrentStatus(in.notifyCurrentStatus) 462 .setVideoBitrateBps(0) 463 .build(); 464 } 465 466 /** Converts HAL MediaQualityStatus to {@link MediaQualityStatus} */ convertMediaQualityStatus( final android.hardware.radio.ims.media.MediaQualityStatus in)467 public static MediaQualityStatus convertMediaQualityStatus( 468 final android.hardware.radio.ims.media.MediaQualityStatus in) { 469 return (in == null) ? null : new MediaQualityStatus.Builder() 470 .setRtpInactivityTimeMillis(in.rtpInactivityTimeMillis) 471 .setRtcpInactivityTimeMillis(in.rtcpInactivityTimeMillis) 472 .setRtpPacketLossRate(in.rtpPacketLossRate) 473 .setRtpJitterMillis(in.rtpJitterMillis) 474 .build(); 475 } 476 477 public static android.hardware.radio.ims.media.RtpHeaderExtension convertRtpHeaderExtension(final RtpHeaderExtension in)478 convertRtpHeaderExtension(final RtpHeaderExtension in) { 479 final android.hardware.radio.ims.media.RtpHeaderExtension out; 480 481 if (in == null) { 482 out = null; 483 } else { 484 out = new android.hardware.radio.ims.media.RtpHeaderExtension(); 485 out.localId = in.getLocalIdentifier(); 486 out.data = in.getExtensionData(); 487 } 488 489 return out; 490 } 491 convertRtpHeaderExtension( final android.hardware.radio.ims.media.RtpHeaderExtension in)492 public static RtpHeaderExtension convertRtpHeaderExtension( 493 final android.hardware.radio.ims.media.RtpHeaderExtension in) { 494 return (in == null) ? null : new RtpHeaderExtension(in.localId, in.data); 495 } 496 497 /** Converts HAL CallQuality to {@link CallQuality} */ convertCallQuality( final android.hardware.radio.ims.media.CallQuality in)498 public static CallQuality convertCallQuality( 499 final android.hardware.radio.ims.media.CallQuality in) { 500 return (in == null) ? null : new CallQuality.Builder() 501 .setDownlinkCallQualityLevel(in.downlinkCallQualityLevel) 502 .setUplinkCallQualityLevel(in.uplinkCallQualityLevel) 503 .setCallDurationMillis(in.callDuration) 504 .setNumRtpPacketsTransmitted(in.numRtpPacketsTransmitted) 505 .setNumRtpPacketsReceived(in.numRtpPacketsReceived) 506 .setNumRtpPacketsTransmittedLost(in.numRtpPacketsTransmittedLost) 507 .setNumRtpPacketsNotReceived(in.numRtpPacketsNotReceived) 508 .setAverageRelativeJitter(in.averageRelativeJitter) 509 .setMaxRelativeJitter(in.maxRelativeJitter) 510 .setAverageRoundTripTimeMillis(in.averageRoundTripTime) 511 .setCodecType(in.codecType) 512 .setRtpInactivityDetected(in.rtpInactivityDetected) 513 .setIncomingSilenceDetectedAtCallSetup(in.rxSilenceDetected) 514 .setOutgoingSilenceDetectedAtCallSetup(in.txSilenceDetected) 515 .setNumVoiceFrames(in.numVoiceFrames) 516 .setNumNoDataFrames(in.numNoDataFrames) 517 .setNumDroppedRtpPackets(in.numDroppedRtpPackets) 518 .setMinPlayoutDelayMillis(in.minPlayoutDelayMillis) 519 .setMaxPlayoutDelayMillis(in.maxPlayoutDelayMillis) 520 .setNumRtpSidPacketsReceived(in.numRtpSidPacketsReceived) 521 .setNumRtpDuplicatePackets(in.numRtpDuplicatePackets) 522 .build(); 523 } 524 } 525