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 #include <AudioSession.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaEventHandler.h>
20 #include <ImsMediaAudioUtil.h>
21 #include <AudioConfig.h>
22 #include <string>
23
AudioSession()24 AudioSession::AudioSession()
25 {
26 IMLOGD0("[AudioSession]");
27 std::unique_ptr<MediaQualityAnalyzer> analyzer(new MediaQualityAnalyzer());
28 mMediaQualityAnalyzer = std::move(analyzer);
29 mMediaQualityAnalyzer->setCallback(this);
30 }
31
~AudioSession()32 AudioSession::~AudioSession()
33 {
34 IMLOGD0("[~AudioSession]");
35
36 mMediaQualityAnalyzer->stop();
37
38 while (mListGraphRtpTx.size() > 0)
39 {
40 AudioStreamGraphRtpTx* graph = mListGraphRtpTx.front();
41
42 if (graph->getState() == kStreamStateRunning)
43 {
44 graph->stop();
45 }
46
47 mListGraphRtpTx.pop_front();
48 delete graph;
49 }
50
51 while (mListGraphRtpRx.size() > 0)
52 {
53 AudioStreamGraphRtpRx* graph = mListGraphRtpRx.front();
54
55 if (graph->getState() == kStreamStateRunning)
56 {
57 graph->stop();
58 }
59
60 mListGraphRtpRx.pop_front();
61 delete graph;
62 }
63
64 while (mListGraphRtcp.size() > 0)
65 {
66 AudioStreamGraphRtcp* graph = mListGraphRtcp.front();
67
68 if (graph->getState() == kStreamStateRunning)
69 {
70 graph->stop();
71 }
72
73 mListGraphRtcp.pop_front();
74 delete graph;
75 }
76 }
77
getState()78 SessionState AudioSession::getState()
79 {
80 SessionState state = kSessionStateOpened;
81
82 for (auto& graph : mListGraphRtpTx)
83 {
84 if (graph != nullptr && graph->getState() == kStreamStateRunning)
85 {
86 state = kSessionStateSending;
87 break;
88 }
89 }
90
91 for (auto& graph : mListGraphRtpRx)
92 {
93 if (graph != nullptr && graph->getState() == kStreamStateRunning)
94 {
95 return state == kSessionStateSending ? kSessionStateActive : kSessionStateReceiving;
96 }
97 }
98
99 for (auto& graph : mListGraphRtcp)
100 {
101 if (graph != nullptr && graph->getState() == kStreamStateRunning)
102 {
103 return state == kSessionStateSending ? kSessionStateSending : kSessionStateSuspended;
104 }
105 }
106
107 return state;
108 }
109
startGraph(RtpConfig * config)110 ImsMediaResult AudioSession::startGraph(RtpConfig* config)
111 {
112 IMLOGI0("[startGraph]");
113
114 if (config == nullptr)
115 {
116 return RESULT_INVALID_PARAM;
117 }
118
119 AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
120
121 if (std::strcmp(pConfig->getRemoteAddress().c_str(), "") == 0)
122 {
123 return RESULT_INVALID_PARAM;
124 }
125
126 IMLOGI1("[startGraph] state[%d]", getState());
127
128 if (mMediaQualityAnalyzer != nullptr)
129 {
130 mMediaQualityAnalyzer->setConfig(reinterpret_cast<AudioConfig*>(config));
131 mMediaQualityAnalyzer->start();
132 }
133
134 ImsMediaResult ret = RESULT_NOT_READY;
135 IMLOGD1("[startGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
136
137 AudioStreamGraphRtpTx* graphTx = AudioStreamGraph::findGraph(mListGraphRtpTx,
138 [&config](AudioStreamGraphRtpTx* graph)
139 {
140 return graph != nullptr && graph->isSameGraph(config);
141 });
142
143 if (graphTx != nullptr)
144 {
145 ret = graphTx->update(config);
146
147 if (ret != RESULT_SUCCESS)
148 {
149 IMLOGE1("[startGraph] update error[%d]", ret);
150 return ret;
151 }
152 }
153 else
154 {
155 mListGraphRtpTx.push_back(new AudioStreamGraphRtpTx(this, mRtpFd));
156
157 if (mListGraphRtpTx.back()->create(config) == RESULT_SUCCESS)
158 {
159 ret = mListGraphRtpTx.back()->start();
160
161 if (ret != RESULT_SUCCESS)
162 {
163 IMLOGE1("[startGraph] start error[%d]", ret);
164 return ret;
165 }
166 }
167 }
168
169 IMLOGD1("[startGraph] ListGraphRtpRx size[%d]", mListGraphRtpRx.size());
170
171 AudioStreamGraphRtpRx* graphRx = AudioStreamGraph::findGraph(mListGraphRtpRx,
172 [&config](AudioStreamGraphRtpRx* graph)
173 {
174 return graph != nullptr && graph->isSameGraph(config);
175 });
176
177 if (graphRx != nullptr)
178 {
179 graphRx->setMediaQualityThreshold(&mThreshold);
180 ret = graphRx->update(config);
181
182 if (ret != RESULT_SUCCESS)
183 {
184 IMLOGE1("[startGraph] update error[%d]", ret);
185 return ret;
186 }
187 }
188 else
189 {
190 mListGraphRtpRx.push_back(new AudioStreamGraphRtpRx(this, mRtpFd));
191
192 if (mListGraphRtpRx.back()->create(config) == RESULT_SUCCESS)
193 {
194 mListGraphRtpRx.back()->setMediaQualityThreshold(&mThreshold);
195 ret = mListGraphRtpRx.back()->start();
196
197 if (ret != RESULT_SUCCESS)
198 {
199 IMLOGE1("[startGraph] start error[%d]", ret);
200 return ret;
201 }
202 }
203 }
204
205 IMLOGD1("[startGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
206
207 AudioStreamGraphRtcp* graphRtcp = AudioStreamGraph::findGraph(mListGraphRtcp,
208 [&config](AudioStreamGraphRtcp* graph)
209 {
210 return graph != nullptr && graph->isSameGraph(config);
211 });
212
213 if (graphRtcp != nullptr)
214 {
215 graphRtcp->setMediaQualityThreshold(&mThreshold);
216 ret = graphRtcp->update(config);
217
218 if (ret != RESULT_SUCCESS)
219 {
220 IMLOGE1("[startGraph] update error[%d]", ret);
221 return ret;
222 }
223 }
224 else
225 {
226 mListGraphRtcp.push_back(new AudioStreamGraphRtcp(this, mRtcpFd));
227
228 if (mListGraphRtcp.back()->create(config) == RESULT_SUCCESS)
229 {
230 mListGraphRtcp.back()->setMediaQualityThreshold(&mThreshold);
231 ret = mListGraphRtcp.back()->start();
232
233 if (ret != RESULT_SUCCESS)
234 {
235 IMLOGE1("[startGraph] start error[%d]", ret);
236 return ret;
237 }
238 }
239 }
240
241 return ret;
242 }
243
addGraph(RtpConfig * config,bool enableRtcp)244 ImsMediaResult AudioSession::addGraph(RtpConfig* config, bool enableRtcp)
245 {
246 IMLOGD1("[addGraph], enable rtcp[%d]", enableRtcp);
247
248 if (config == nullptr || std::strcmp(config->getRemoteAddress().c_str(), "") == 0)
249 {
250 return RESULT_INVALID_PARAM;
251 }
252
253 if (IsGraphAlreadyExist(config) || mListGraphRtpTx.empty())
254 {
255 return startGraph(config);
256 }
257
258 if (enableRtcp) // update current graph to inactive mode
259 {
260 for (auto& graph : mListGraphRtpTx)
261 {
262 if (graph != nullptr)
263 {
264 graph->stop();
265 }
266 }
267
268 for (auto& graph : mListGraphRtpRx)
269 {
270 if (graph != nullptr)
271 {
272 graph->stop();
273 }
274 }
275
276 for (auto& graph : mListGraphRtcp)
277 {
278 if (graph != nullptr && graph->getState() != kStreamStateRunning)
279 {
280 graph->start();
281 }
282 }
283
284 return startGraph(config);
285 }
286 else
287 {
288 return confirmGraph(config);
289 }
290 }
291
confirmGraph(RtpConfig * config)292 ImsMediaResult AudioSession::confirmGraph(RtpConfig* config)
293 {
294 if (config == nullptr || std::strcmp(config->getRemoteAddress().c_str(), "") == 0)
295 {
296 return RESULT_INVALID_PARAM;
297 }
298
299 if (mListGraphRtpTx.empty() || mListGraphRtpRx.empty() || mListGraphRtcp.empty())
300 {
301 return startGraph(config);
302 }
303
304 /** Stop and delete unmatched running instances of StreamGraph. */
305 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
306 iter != mListGraphRtpTx.end();)
307 {
308 AudioStreamGraphRtpTx* graph = *iter;
309
310 if (graph != nullptr && !graph->isSameGraph(config))
311 {
312 graph->stop();
313 iter = mListGraphRtpTx.erase(iter);
314 delete graph;
315 }
316 else
317 {
318 iter++;
319 }
320 }
321
322 IMLOGD1("[confirmGraph] mListGraphTx size[%d]", mListGraphRtpTx.size());
323
324 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
325 iter != mListGraphRtpRx.end();)
326 {
327 AudioStreamGraphRtpRx* graph = *iter;
328
329 if (graph != nullptr && !graph->isSameGraph(config))
330 {
331 graph->stop();
332 iter = mListGraphRtpRx.erase(iter);
333 delete graph;
334 }
335 else
336 {
337 iter++;
338 }
339 }
340
341 IMLOGD1("[confirmGraph] mListGraphRx size[%d]", mListGraphRtpRx.size());
342
343 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
344 iter != mListGraphRtcp.end();)
345 {
346 AudioStreamGraphRtcp* graph = *iter;
347
348 if (graph != nullptr && !graph->isSameGraph(config))
349 {
350 graph->stop();
351 iter = mListGraphRtcp.erase(iter);
352 delete graph;
353 }
354 else
355 {
356 iter++;
357 }
358 }
359
360 IMLOGD1("[confirmGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
361
362 return startGraph(config);
363 }
364
deleteGraph(RtpConfig * config)365 ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
366 {
367 IMLOGI0("[deleteGraph]");
368 bool bFound = false;
369
370 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
371 iter != mListGraphRtpTx.end();)
372 {
373 AudioStreamGraphRtpTx* graph = *iter;
374
375 if (graph == nullptr)
376 {
377 continue;
378 }
379
380 if (graph->isSameGraph(config))
381 {
382 graph->stop();
383 iter = mListGraphRtpTx.erase(iter);
384 delete graph;
385 bFound = true;
386 break;
387 }
388 else
389 {
390 iter++;
391 }
392 }
393
394 if (bFound == false)
395 {
396 return RESULT_INVALID_PARAM;
397 }
398
399 IMLOGD1("[deleteGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
400
401 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
402 iter != mListGraphRtpRx.end();)
403 {
404 AudioStreamGraphRtpRx* graph = *iter;
405
406 if (graph == nullptr)
407 {
408 continue;
409 }
410
411 if (graph->isSameGraph(config))
412 {
413 if (graph->getState() == kStreamStateRunning)
414 {
415 graph->stop();
416 }
417
418 iter = mListGraphRtpRx.erase(iter);
419 delete graph;
420 break;
421 }
422 else
423 {
424 iter++;
425 }
426 }
427
428 IMLOGD1("[deleteGraph] mListGraphRtpRx size[%d]", mListGraphRtpRx.size());
429
430 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
431 iter != mListGraphRtcp.end();)
432 {
433 AudioStreamGraphRtcp* graph = *iter;
434
435 if (graph == nullptr)
436 {
437 continue;
438 }
439
440 if (graph->isSameGraph(config))
441 {
442 if (graph->getState() == kStreamStateRunning)
443 {
444 graph->stop();
445 }
446
447 iter = mListGraphRtcp.erase(iter);
448 delete graph;
449 break;
450 }
451 else
452 {
453 iter++;
454 }
455 }
456
457 IMLOGD1("[deleteGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
458 return RESULT_SUCCESS;
459 }
460
onEvent(int32_t type,uint64_t param1,uint64_t param2)461 void AudioSession::onEvent(int32_t type, uint64_t param1, uint64_t param2)
462 {
463 switch (type)
464 {
465 case kImsMediaEventStateChanged:
466 if (mState != getState())
467 {
468 mState = getState();
469 }
470 break;
471 case kImsMediaEventNotifyError:
472 break;
473 case kImsMediaEventFirstPacketReceived:
474 ImsMediaEventHandler::SendEvent(
475 "AUDIO_RESPONSE_EVENT", kAudioFirstMediaPacketInd, mSessionId, param1, param2);
476 break;
477 case kImsMediaEventHeaderExtensionReceived:
478 ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioRtpHeaderExtensionInd,
479 mSessionId, param1, param2);
480 break;
481 case kImsMediaEventMediaQualityStatus:
482 ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioMediaQualityStatusInd,
483 mSessionId, param1, param2);
484 break;
485 case kAudioTriggerAnbrQueryInd:
486 /** TODO: add implementation */
487 break;
488 case kAudioDtmfReceivedInd:
489 ImsMediaEventHandler::SendEvent(
490 "AUDIO_RESPONSE_EVENT", kAudioDtmfReceivedInd, mSessionId, param1, param2);
491 break;
492 case kAudioCallQualityChangedInd:
493 ImsMediaEventHandler::SendEvent(
494 "AUDIO_RESPONSE_EVENT", kAudioCallQualityChangedInd, mSessionId, param1);
495 break;
496 case kRequestAudioCmr:
497 case kRequestAudioCmrEvs:
498 case kRequestSendRtcpXrReport:
499 ImsMediaEventHandler::SendEvent(
500 "AUDIO_REQUEST_EVENT", type, mSessionId, param1, param2);
501 break;
502 case kRequestRoundTripTimeDelayUpdate:
503 case kRequestAudioPlayingStatus:
504 case kCollectPacketInfo:
505 case kCollectOptionalInfo:
506 case kCollectRxRtpStatus:
507 case kCollectJitterBufferSize:
508 case kGetRtcpXrReportBlock:
509 if (mMediaQualityAnalyzer != nullptr)
510 {
511 mMediaQualityAnalyzer->SendEvent(type, param1, param2);
512 }
513 else
514 {
515 switch (type)
516 {
517 case kCollectRxRtpStatus:
518 case kCollectOptionalInfo:
519 if (param1)
520 {
521 delete reinterpret_cast<SessionCallbackParameter*>(param1);
522 }
523 break;
524
525 case kCollectPacketInfo:
526 if (param2)
527 {
528 delete reinterpret_cast<RtpPacket*>(param2);
529 }
530 break;
531 }
532 }
533 break;
534 default:
535 break;
536 }
537 }
538
setMediaQualityThreshold(const MediaQualityThreshold & threshold)539 void AudioSession::setMediaQualityThreshold(const MediaQualityThreshold& threshold)
540 {
541 IMLOGI0("[setMediaQualityThreshold]");
542 mThreshold = threshold;
543
544 if (mMediaQualityAnalyzer != nullptr)
545 {
546 mMediaQualityAnalyzer->setMediaQualityThreshold(threshold);
547 }
548 }
549
sendDtmf(char digit,int duration)550 void AudioSession::sendDtmf(char digit, int duration)
551 {
552 if (mListGraphRtpTx.empty())
553 {
554 return;
555 }
556
557 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
558 iter != mListGraphRtpTx.end(); iter++)
559 {
560 AudioStreamGraphRtpTx* graph = *iter;
561
562 if (graph != nullptr && graph->getState() == kStreamStateRunning)
563 {
564 graph->sendDtmf(digit, duration);
565 }
566 }
567 }
568
IsGraphAlreadyExist(RtpConfig * config)569 bool AudioSession::IsGraphAlreadyExist(RtpConfig* config)
570 {
571 if (mListGraphRtpTx.size() != 0)
572 {
573 for (auto& graph : mListGraphRtpTx)
574 {
575 if (graph != nullptr && graph->isSameGraph(config))
576 {
577 return true;
578 }
579 }
580 }
581
582 return false;
583 }
584
getGraphSize(ImsMediaStreamType type)585 uint32_t AudioSession::getGraphSize(ImsMediaStreamType type)
586 {
587 switch (type)
588 {
589 case kStreamRtpTx:
590 return mListGraphRtpTx.size();
591 case kStreamRtpRx:
592 return mListGraphRtpRx.size();
593 case kStreamRtcp:
594 return mListGraphRtcp.size();
595 }
596
597 return 0;
598 }
599
sendRtpHeaderExtension(std::list<RtpHeaderExtension> * listExtension)600 void AudioSession::sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
601 {
602 for (auto& graph : mListGraphRtpTx)
603 {
604 if (graph != nullptr)
605 {
606 graph->sendRtpHeaderExtension(listExtension);
607 }
608 }
609 }
610
SendInternalEvent(int32_t type,uint64_t param1,uint64_t param2)611 void AudioSession::SendInternalEvent(int32_t type, uint64_t param1, uint64_t param2)
612 {
613 switch (type)
614 {
615 case kRequestAudioCmr:
616 case kRequestAudioCmrEvs:
617 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
618 iter != mListGraphRtpTx.end(); iter++)
619 {
620 AudioStreamGraphRtpTx* graph = *iter;
621
622 if (graph != nullptr && graph->getState() == kStreamStateRunning)
623 {
624 type == kRequestAudioCmr ? graph->processCmr(static_cast<uint32_t>(param1))
625 : graph->processCmr(static_cast<uint32_t>(param1),
626 static_cast<uint32_t>(param2));
627 }
628 }
629
630 if (type == kRequestAudioCmrEvs)
631 {
632 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
633 iter != mListGraphRtpRx.end(); iter++)
634 {
635 AudioStreamGraphRtpRx* graph = *iter;
636
637 if (graph != nullptr && graph->getState() == kStreamStateRunning)
638 {
639 graph->processCmr(
640 static_cast<uint32_t>(param1), static_cast<uint32_t>(param2));
641 }
642 }
643 }
644 break;
645 case kRequestSendRtcpXrReport:
646 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
647 iter != mListGraphRtcp.end(); iter++)
648 {
649 AudioStreamGraphRtcp* graph = *iter;
650
651 if (graph != nullptr && graph->getState() == kStreamStateRunning)
652 {
653 graph->OnEvent(type, param1, param2);
654 }
655 }
656 break;
657 default:
658 break;
659 }
660 }