• 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 #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