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