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* audioConfig = reinterpret_cast<AudioConfig*>(config);
120
121 if (std::strcmp(audioConfig->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 if (audioConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_NO_FLOW)
131 {
132 mMediaQualityAnalyzer->stop();
133 }
134 else
135 {
136 mMediaQualityAnalyzer->setConfig(audioConfig);
137 mMediaQualityAnalyzer->start();
138 }
139 }
140
141 ImsMediaResult ret = RESULT_NOT_READY;
142 IMLOGD1("[startGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
143
144 AudioStreamGraphRtpTx* graphTx = AudioStreamGraph::findGraph(mListGraphRtpTx,
145 [&config](AudioStreamGraphRtpTx* graph)
146 {
147 return graph != nullptr && graph->isSameGraph(config);
148 });
149
150 if (graphTx != nullptr)
151 {
152 ret = graphTx->update(config);
153
154 if (ret != RESULT_SUCCESS)
155 {
156 IMLOGE1("[startGraph] update error[%d]", ret);
157 return ret;
158 }
159 }
160 else
161 {
162 mListGraphRtpTx.push_back(new AudioStreamGraphRtpTx(this, mRtpFd));
163
164 if (mListGraphRtpTx.back()->create(config) == RESULT_SUCCESS)
165 {
166 ret = mListGraphRtpTx.back()->start();
167
168 if (ret != RESULT_SUCCESS)
169 {
170 IMLOGE1("[startGraph] start error[%d]", ret);
171 return ret;
172 }
173 }
174 }
175
176 IMLOGD1("[startGraph] ListGraphRtpRx size[%d]", mListGraphRtpRx.size());
177
178 AudioStreamGraphRtpRx* graphRx = AudioStreamGraph::findGraph(mListGraphRtpRx,
179 [&config](AudioStreamGraphRtpRx* graph)
180 {
181 return graph != nullptr && graph->isSameGraph(config);
182 });
183
184 if (graphRx != nullptr)
185 {
186 graphRx->setMediaQualityThreshold(&mThreshold);
187 ret = graphRx->update(config);
188
189 if (ret != RESULT_SUCCESS)
190 {
191 IMLOGE1("[startGraph] update error[%d]", ret);
192 return ret;
193 }
194 }
195 else
196 {
197 mListGraphRtpRx.push_back(new AudioStreamGraphRtpRx(this, mRtpFd));
198
199 if (mListGraphRtpRx.back()->create(config) == RESULT_SUCCESS)
200 {
201 mListGraphRtpRx.back()->setMediaQualityThreshold(&mThreshold);
202 ret = mListGraphRtpRx.back()->start();
203
204 if (ret != RESULT_SUCCESS)
205 {
206 IMLOGE1("[startGraph] start error[%d]", ret);
207 return ret;
208 }
209 }
210 }
211
212 IMLOGD1("[startGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
213
214 AudioStreamGraphRtcp* graphRtcp = AudioStreamGraph::findGraph(mListGraphRtcp,
215 [&config](AudioStreamGraphRtcp* graph)
216 {
217 return graph != nullptr && graph->isSameGraph(config);
218 });
219
220 if (graphRtcp != nullptr)
221 {
222 graphRtcp->setMediaQualityThreshold(&mThreshold);
223 ret = graphRtcp->update(config);
224
225 if (ret != RESULT_SUCCESS)
226 {
227 IMLOGE1("[startGraph] update error[%d]", ret);
228 return ret;
229 }
230 }
231 else
232 {
233 mListGraphRtcp.push_back(new AudioStreamGraphRtcp(this, mRtcpFd));
234
235 if (mListGraphRtcp.back()->create(config) == RESULT_SUCCESS)
236 {
237 mListGraphRtcp.back()->setMediaQualityThreshold(&mThreshold);
238 ret = mListGraphRtcp.back()->start();
239
240 if (ret != RESULT_SUCCESS)
241 {
242 IMLOGE1("[startGraph] start error[%d]", ret);
243 return ret;
244 }
245 }
246 }
247
248 return ret;
249 }
250
addGraph(RtpConfig * config,bool enableRtcp)251 ImsMediaResult AudioSession::addGraph(RtpConfig* config, bool enableRtcp)
252 {
253 IMLOGD1("[addGraph], enable rtcp[%d]", enableRtcp);
254
255 if (config == nullptr || std::strcmp(config->getRemoteAddress().c_str(), "") == 0)
256 {
257 return RESULT_INVALID_PARAM;
258 }
259
260 if (IsGraphAlreadyExist(config) || mListGraphRtpTx.empty())
261 {
262 return startGraph(config);
263 }
264
265 if (enableRtcp) // update current graph to inactive mode
266 {
267 for (auto& graph : mListGraphRtpTx)
268 {
269 if (graph != nullptr)
270 {
271 graph->stop();
272 }
273 }
274
275 for (auto& graph : mListGraphRtpRx)
276 {
277 if (graph != nullptr)
278 {
279 graph->stop();
280 }
281 }
282
283 for (auto& graph : mListGraphRtcp)
284 {
285 if (graph != nullptr && graph->getState() != kStreamStateRunning)
286 {
287 graph->start();
288 }
289 }
290
291 return startGraph(config);
292 }
293 else
294 {
295 return confirmGraph(config);
296 }
297 }
298
confirmGraph(RtpConfig * config)299 ImsMediaResult AudioSession::confirmGraph(RtpConfig* config)
300 {
301 if (config == nullptr || std::strcmp(config->getRemoteAddress().c_str(), "") == 0)
302 {
303 return RESULT_INVALID_PARAM;
304 }
305
306 if (mListGraphRtpTx.empty() || mListGraphRtpRx.empty() || mListGraphRtcp.empty())
307 {
308 return startGraph(config);
309 }
310
311 /** Stop and delete unmatched running instances of StreamGraph. */
312 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
313 iter != mListGraphRtpTx.end();)
314 {
315 AudioStreamGraphRtpTx* graph = *iter;
316
317 if (graph != nullptr && !graph->isSameGraph(config))
318 {
319 graph->stop();
320 iter = mListGraphRtpTx.erase(iter);
321 delete graph;
322 }
323 else
324 {
325 iter++;
326 }
327 }
328
329 IMLOGD1("[confirmGraph] mListGraphTx size[%d]", mListGraphRtpTx.size());
330
331 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
332 iter != mListGraphRtpRx.end();)
333 {
334 AudioStreamGraphRtpRx* graph = *iter;
335
336 if (graph != nullptr && !graph->isSameGraph(config))
337 {
338 graph->stop();
339 iter = mListGraphRtpRx.erase(iter);
340 delete graph;
341 }
342 else
343 {
344 iter++;
345 }
346 }
347
348 IMLOGD1("[confirmGraph] mListGraphRx size[%d]", mListGraphRtpRx.size());
349
350 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
351 iter != mListGraphRtcp.end();)
352 {
353 AudioStreamGraphRtcp* graph = *iter;
354
355 if (graph != nullptr && !graph->isSameGraph(config))
356 {
357 graph->stop();
358 iter = mListGraphRtcp.erase(iter);
359 delete graph;
360 }
361 else
362 {
363 iter++;
364 }
365 }
366
367 IMLOGD1("[confirmGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
368
369 return startGraph(config);
370 }
371
deleteGraph(RtpConfig * config)372 ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
373 {
374 IMLOGI0("[deleteGraph]");
375 bool bFound = false;
376
377 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
378 iter != mListGraphRtpTx.end();)
379 {
380 AudioStreamGraphRtpTx* graph = *iter;
381
382 if (graph == nullptr)
383 {
384 continue;
385 }
386
387 if (graph->isSameGraph(config))
388 {
389 graph->stop();
390 iter = mListGraphRtpTx.erase(iter);
391 delete graph;
392 bFound = true;
393 break;
394 }
395 else
396 {
397 iter++;
398 }
399 }
400
401 if (bFound == false)
402 {
403 return RESULT_INVALID_PARAM;
404 }
405
406 IMLOGD1("[deleteGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
407
408 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
409 iter != mListGraphRtpRx.end();)
410 {
411 AudioStreamGraphRtpRx* graph = *iter;
412
413 if (graph == nullptr)
414 {
415 continue;
416 }
417
418 if (graph->isSameGraph(config))
419 {
420 if (graph->getState() == kStreamStateRunning)
421 {
422 graph->stop();
423 }
424
425 iter = mListGraphRtpRx.erase(iter);
426 delete graph;
427 break;
428 }
429 else
430 {
431 iter++;
432 }
433 }
434
435 IMLOGD1("[deleteGraph] mListGraphRtpRx size[%d]", mListGraphRtpRx.size());
436
437 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
438 iter != mListGraphRtcp.end();)
439 {
440 AudioStreamGraphRtcp* graph = *iter;
441
442 if (graph == nullptr)
443 {
444 continue;
445 }
446
447 if (graph->isSameGraph(config))
448 {
449 if (graph->getState() == kStreamStateRunning)
450 {
451 graph->stop();
452 }
453
454 iter = mListGraphRtcp.erase(iter);
455 delete graph;
456 break;
457 }
458 else
459 {
460 iter++;
461 }
462 }
463
464 IMLOGD1("[deleteGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
465 return RESULT_SUCCESS;
466 }
467
onEvent(int32_t type,uint64_t param1,uint64_t param2)468 void AudioSession::onEvent(int32_t type, uint64_t param1, uint64_t param2)
469 {
470 switch (type)
471 {
472 case kImsMediaEventStateChanged:
473 if (mState != getState())
474 {
475 mState = getState();
476 }
477 break;
478 case kImsMediaEventNotifyError:
479 break;
480 case kImsMediaEventFirstPacketReceived:
481 ImsMediaEventHandler::SendEvent(
482 "AUDIO_RESPONSE_EVENT", kAudioFirstMediaPacketInd, mSessionId, param1, param2);
483 break;
484 case kImsMediaEventHeaderExtensionReceived:
485 ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioRtpHeaderExtensionInd,
486 mSessionId, param1, param2);
487 break;
488 case kImsMediaEventMediaQualityStatus:
489 ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioMediaQualityStatusInd,
490 mSessionId, param1, param2);
491 break;
492 case kAudioTriggerAnbrQueryInd:
493 ImsMediaEventHandler::SendEvent(
494 "AUDIO_RESPONSE_EVENT", kAudioTriggerAnbrQueryInd, mSessionId, param1);
495 break;
496 case kAudioDtmfReceivedInd:
497 ImsMediaEventHandler::SendEvent(
498 "AUDIO_RESPONSE_EVENT", kAudioDtmfReceivedInd, mSessionId, param1, param2);
499 break;
500 case kAudioCallQualityChangedInd:
501 ImsMediaEventHandler::SendEvent(
502 "AUDIO_RESPONSE_EVENT", kAudioCallQualityChangedInd, mSessionId, param1);
503 break;
504 case kAudioNotifyRtpReceptionStats:
505 ImsMediaEventHandler::SendEvent(
506 "AUDIO_RESPONSE_EVENT", kAudioNotifyRtpReceptionStats, mSessionId, param1);
507 break;
508 case kRequestAudioCmr:
509 case kRequestAudioCmrEvs:
510 case kRequestSendRtcpXrReport:
511 ImsMediaEventHandler::SendEvent(
512 "AUDIO_REQUEST_EVENT", type, mSessionId, param1, param2);
513 break;
514 case kRequestRoundTripTimeDelayUpdate:
515 case kRequestAudioPlayingStatus:
516 case kCollectPacketInfo:
517 case kCollectOptionalInfo:
518 case kCollectRxRtpStatus:
519 case kCollectJitterBufferSize:
520 case kGetRtcpXrReportBlock:
521 if (mMediaQualityAnalyzer != nullptr)
522 {
523 mMediaQualityAnalyzer->SendEvent(type, param1, param2);
524 }
525 else
526 {
527 switch (type)
528 {
529 case kCollectRxRtpStatus:
530 case kCollectOptionalInfo:
531 if (param1)
532 {
533 delete reinterpret_cast<SessionCallbackParameter*>(param1);
534 }
535 break;
536
537 case kCollectPacketInfo:
538 if (param1 == kStreamRtcp)
539 {
540 if (param2)
541 {
542 delete reinterpret_cast<RtcpSr*>(param2);
543 }
544 }
545 else if (param2)
546 {
547 delete reinterpret_cast<RtpPacket*>(param2);
548 }
549 break;
550 }
551 }
552 break;
553 default:
554 break;
555 }
556 }
557
setMediaQualityThreshold(const MediaQualityThreshold & threshold)558 void AudioSession::setMediaQualityThreshold(const MediaQualityThreshold& threshold)
559 {
560 IMLOGI0("[setMediaQualityThreshold]");
561 mThreshold = threshold;
562
563 if (mMediaQualityAnalyzer != nullptr)
564 {
565 mMediaQualityAnalyzer->setMediaQualityThreshold(threshold);
566 }
567 }
568
sendDtmf(char digit,int duration)569 void AudioSession::sendDtmf(char digit, int duration)
570 {
571 if (mListGraphRtpTx.empty())
572 {
573 return;
574 }
575
576 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
577 iter != mListGraphRtpTx.end(); iter++)
578 {
579 AudioStreamGraphRtpTx* graph = *iter;
580
581 if (graph != nullptr && graph->getState() == kStreamStateRunning)
582 {
583 graph->sendDtmf(digit, duration);
584 }
585 }
586 }
587
requestRtpReceptionStats(int32_t intervalMs)588 void AudioSession::requestRtpReceptionStats(int32_t intervalMs)
589 {
590 if (mMediaQualityAnalyzer != nullptr)
591 {
592 mMediaQualityAnalyzer->setNotifyRtpReceptionStatsInterval(intervalMs);
593 }
594 }
595
adjustDelay(const int32_t delayMs)596 void AudioSession::adjustDelay(const int32_t delayMs)
597 {
598 if (mListGraphRtpRx.empty())
599 {
600 return;
601 }
602
603 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
604 iter != mListGraphRtpRx.end(); iter++)
605 {
606 AudioStreamGraphRtpRx* graph = *iter;
607
608 if (graph != nullptr && graph->getState() == kStreamStateRunning)
609 {
610 graph->adjustDelay(delayMs);
611 }
612 }
613 }
614
IsGraphAlreadyExist(RtpConfig * config)615 bool AudioSession::IsGraphAlreadyExist(RtpConfig* config)
616 {
617 if (mListGraphRtpTx.size() != 0)
618 {
619 for (auto& graph : mListGraphRtpTx)
620 {
621 if (graph != nullptr && graph->isSameGraph(config))
622 {
623 return true;
624 }
625 }
626 }
627
628 return false;
629 }
630
getGraphSize(ImsMediaStreamType type)631 uint32_t AudioSession::getGraphSize(ImsMediaStreamType type)
632 {
633 switch (type)
634 {
635 case kStreamRtpTx:
636 return mListGraphRtpTx.size();
637 case kStreamRtpRx:
638 return mListGraphRtpRx.size();
639 case kStreamRtcp:
640 return mListGraphRtcp.size();
641 }
642
643 return 0;
644 }
645
sendRtpHeaderExtension(std::list<RtpHeaderExtension> * listExtension)646 void AudioSession::sendRtpHeaderExtension(std::list<RtpHeaderExtension>* listExtension)
647 {
648 for (auto& graph : mListGraphRtpTx)
649 {
650 if (graph != nullptr)
651 {
652 graph->sendRtpHeaderExtension(listExtension);
653 }
654 }
655 }
656
SendInternalEvent(int32_t type,uint64_t param1,uint64_t param2)657 void AudioSession::SendInternalEvent(int32_t type, uint64_t param1, uint64_t param2)
658 {
659 switch (type)
660 {
661 case kRequestAudioCmr:
662 case kRequestAudioCmrEvs:
663 for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
664 iter != mListGraphRtpTx.end(); iter++)
665 {
666 AudioStreamGraphRtpTx* graph = *iter;
667
668 if (graph != nullptr && graph->getState() == kStreamStateRunning)
669 {
670 type == kRequestAudioCmr ? graph->processCmr(static_cast<uint32_t>(param1))
671 : graph->processCmr(static_cast<uint32_t>(param1),
672 static_cast<uint32_t>(param2));
673 }
674 }
675
676 if (type == kRequestAudioCmrEvs)
677 {
678 for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
679 iter != mListGraphRtpRx.end(); iter++)
680 {
681 AudioStreamGraphRtpRx* graph = *iter;
682
683 if (graph != nullptr && graph->getState() == kStreamStateRunning)
684 {
685 graph->processCmr(
686 static_cast<uint32_t>(param1), static_cast<uint32_t>(param2));
687 }
688 }
689 }
690 break;
691 case kRequestSendRtcpXrReport:
692 for (std::list<AudioStreamGraphRtcp*>::iterator iter = mListGraphRtcp.begin();
693 iter != mListGraphRtcp.end(); iter++)
694 {
695 AudioStreamGraphRtcp* graph = *iter;
696
697 if (graph != nullptr && graph->getState() == kStreamStateRunning)
698 {
699 graph->OnEvent(type, param1, param2);
700 }
701 }
702 break;
703 default:
704 break;
705 }
706 }
707
deactivate()708 bool AudioSession::deactivate()
709 {
710 IMLOGI0("[deactivate]");
711
712 for (auto& graph : mListGraphRtpTx)
713 {
714 if (graph != nullptr)
715 {
716 graph->stop();
717 }
718 }
719
720 for (auto& graph : mListGraphRtpRx)
721 {
722 if (graph != nullptr)
723 {
724 graph->stop();
725 }
726 }
727
728 SessionState state = getState();
729 if (state == kSessionStateActive || state == kSessionStateReceiving ||
730 state == kSessionStateSending)
731 {
732 return false;
733 }
734
735 return true;
736 }
737