• 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* 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 }