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