• 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 <AudioManager.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaNetworkUtil.h>
20 #include <MediaQualityStatus.h>
21 
22 using namespace android;
23 
24 AudioManager* AudioManager::sManager = nullptr;
25 
AudioManager()26 AudioManager::AudioManager()
27 {
28     mRequestHandler.Init("AUDIO_REQUEST_EVENT");
29     mResponseHandler.Init("AUDIO_RESPONSE_EVENT");
30 }
31 
~AudioManager()32 AudioManager::~AudioManager()
33 {
34     mRequestHandler.Deinit();
35     mResponseHandler.Deinit();
36     sManager = nullptr;
37 }
38 
getInstance()39 AudioManager* AudioManager::getInstance()
40 {
41     if (sManager == nullptr)
42     {
43         sManager = new AudioManager();
44     }
45 
46     return sManager;
47 }
48 
getState(int sessionId)49 int AudioManager::getState(int sessionId)
50 {
51     auto session = mSessions.find(sessionId);
52     if (session != mSessions.end())
53     {
54         return (session->second)->getState();
55     }
56     else
57     {
58         return kSessionStateClosed;
59     }
60 }
61 
openSession(int sessionId,int rtpFd,int rtcpFd,AudioConfig * config)62 ImsMediaResult AudioManager::openSession(int sessionId, int rtpFd, int rtcpFd, AudioConfig* config)
63 {
64     IMLOGI1("[openSession] sessionId[%d]", sessionId);
65 
66     if (rtpFd == -1 || rtcpFd == -1)
67     {
68         return RESULT_INVALID_PARAM;
69     }
70 
71     if (!mSessions.count(sessionId))
72     {
73         std::unique_ptr<AudioSession> session(new AudioSession());
74         session->setSessionId(sessionId);
75         session->setLocalEndPoint(rtpFd, rtcpFd);
76 
77         if (session->startGraph(config) != RESULT_SUCCESS)
78         {
79             IMLOGI0("[openSession] startGraph failed");
80         }
81 
82         mSessions.insert(std::make_pair(sessionId, std::move(session)));
83     }
84     else
85     {
86         return RESULT_INVALID_PARAM;
87     }
88 
89     return RESULT_SUCCESS;
90 }
91 
closeSession(int sessionId)92 ImsMediaResult AudioManager::closeSession(int sessionId)
93 {
94     IMLOGI1("[closeSession] sessionId[%d]", sessionId);
95     if (mSessions.count(sessionId))
96     {
97         mSessions.erase(sessionId);
98         return RESULT_SUCCESS;
99     }
100     return RESULT_INVALID_PARAM;
101 }
102 
modifySession(int sessionId,AudioConfig * config)103 ImsMediaResult AudioManager::modifySession(int sessionId, AudioConfig* config)
104 {
105     auto session = mSessions.find(sessionId);
106     IMLOGI1("[modifySession] sessionId[%d]", sessionId);
107     if (session != mSessions.end())
108     {
109         if ((config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE ||
110                     config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
111                     config->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY) &&
112                 isOtherSessionActive(sessionId))
113         {
114             return RESULT_NO_RESOURCES;
115         }
116         else
117         {
118             if ((session->second)->IsGraphAlreadyExist(config) ||
119                     (session->second)->getGraphSize(kStreamRtpTx) == 0)
120             {
121                 return (session->second)->startGraph(config);
122             }
123             else
124             {
125                 return (session->second)->addGraph(config, false);
126             }
127         }
128     }
129     else
130     {
131         IMLOGE1("[modifySession] no session id[%d]", sessionId);
132         return RESULT_INVALID_PARAM;
133     }
134 }
135 
addConfig(int sessionId,AudioConfig * config)136 ImsMediaResult AudioManager::addConfig(int sessionId, AudioConfig* config)
137 {
138     auto session = mSessions.find(sessionId);
139     IMLOGI1("[addConfig] sessionId[%d]", sessionId);
140 
141     if (session != mSessions.end())
142     {
143         return (session->second)->addGraph(config, true);
144     }
145     else
146     {
147         IMLOGE1("[addConfig] no session id[%d]", sessionId);
148         return RESULT_INVALID_PARAM;
149     }
150 }
151 
deleteConfig(int sessionId,AudioConfig * config)152 ImsMediaResult AudioManager::deleteConfig(int sessionId, AudioConfig* config)
153 {
154     auto session = mSessions.find(sessionId);
155     IMLOGI1("[deleteConfig] sessionId[%d]", sessionId);
156     if (session != mSessions.end())
157     {
158         return (session->second)->deleteGraph(config);
159     }
160     else
161     {
162         IMLOGE1("[deleteConfig] no session id[%d]", sessionId);
163         return RESULT_INVALID_PARAM;
164     }
165 }
166 
confirmConfig(int sessionId,AudioConfig * config)167 ImsMediaResult AudioManager::confirmConfig(int sessionId, AudioConfig* config)
168 {
169     auto session = mSessions.find(sessionId);
170     IMLOGI1("[confirmConfig] sessionId[%d]", sessionId);
171     if (session != mSessions.end())
172     {
173         return (session->second)->confirmGraph(config);
174     }
175     else
176     {
177         IMLOGE1("[confirmConfig] no session id[%d]", sessionId);
178         return RESULT_INVALID_PARAM;
179     }
180 }
181 
sendDtmf(int sessionId,char dtmfDigit,int duration)182 void AudioManager::sendDtmf(int sessionId, char dtmfDigit, int duration)
183 {
184     auto session = mSessions.find(sessionId);
185     IMLOGI1("[sendDtmf] sessionId[%d]", sessionId);
186     if (session != mSessions.end())
187     {
188         (session->second)->sendDtmf(dtmfDigit, duration);
189     }
190     else
191     {
192         IMLOGE1("[sendDtmf] no session id[%d]", sessionId);
193     }
194 }
195 
sendRtpHeaderExtension(int sessionId,std::list<RtpHeaderExtension> * listExtension)196 void AudioManager::sendRtpHeaderExtension(
197         int sessionId, std::list<RtpHeaderExtension>* listExtension)
198 {
199     auto session = mSessions.find(sessionId);
200     IMLOGI1("[sendRtpHeaderExtension] sessionId[%d]", sessionId);
201     if (session != mSessions.end())
202     {
203         (session->second)->sendRtpHeaderExtension(listExtension);
204     }
205     else
206     {
207         IMLOGE1("[sendRtpHeaderExtension] no session id[%d]", sessionId);
208     }
209 }
210 
setMediaQualityThreshold(int sessionId,MediaQualityThreshold * threshold)211 void AudioManager::setMediaQualityThreshold(int sessionId, MediaQualityThreshold* threshold)
212 {
213     auto session = mSessions.find(sessionId);
214     IMLOGI1("[setMediaQualityThreshold] sessionId[%d]", sessionId);
215     if (session != mSessions.end())
216     {
217         (session->second)->setMediaQualityThreshold(*threshold);
218     }
219     else
220     {
221         IMLOGE1("[setMediaQualityThreshold] no session id[%d]", sessionId);
222     }
223 }
224 
SendInternalEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)225 void AudioManager::SendInternalEvent(
226         uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
227 {
228     auto session = mSessions.find(sessionId);
229     IMLOGI1("[SendInternalEvent] sessionId[%d]", sessionId);
230 
231     if (session != mSessions.end())
232     {
233         (session->second)->SendInternalEvent(event, paramA, paramB);
234     }
235     else
236     {
237         IMLOGE1("[SendInternalEvent] no session id[%d]", sessionId);
238     }
239 }
240 
sendMessage(const int sessionId,const android::Parcel & parcel)241 void AudioManager::sendMessage(const int sessionId, const android::Parcel& parcel)
242 {
243     int nMsg = parcel.readInt32();
244     status_t err = NO_ERROR;
245     switch (nMsg)
246     {
247         case kAudioOpenSession:
248         {
249             int rtpFd = parcel.readInt32();
250             int rtcpFd = parcel.readInt32();
251             AudioConfig* config = new AudioConfig();
252             err = config->readFromParcel(&parcel);
253 
254             if (err != NO_ERROR && err != -ENODATA)
255             {
256                 IMLOGE1("[sendMessage] error readFromParcel[%d]", err);
257             }
258 
259             EventParamOpenSession* param = new EventParamOpenSession(rtpFd, rtcpFd, config);
260             ImsMediaEventHandler::SendEvent(
261                     "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(param));
262         }
263         break;
264         case kAudioCloseSession:
265             ImsMediaEventHandler::SendEvent("AUDIO_REQUEST_EVENT", nMsg, sessionId);
266             break;
267         case kAudioModifySession:
268         case kAudioAddConfig:
269         case kAudioConfirmConfig:
270         case kAudioDeleteConfig:
271         {
272             AudioConfig* config = new AudioConfig();
273             err = config->readFromParcel(&parcel);
274             if (err != NO_ERROR)
275             {
276                 IMLOGE1("[sendMessage] error readFromParcel[%d]", err);
277             }
278             ImsMediaEventHandler::SendEvent(
279                     "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(config));
280         }
281         break;
282         case kAudioSendDtmf:
283         {
284             EventParamDtmf* param = new EventParamDtmf(parcel.readByte(), parcel.readInt32());
285             ImsMediaEventHandler::SendEvent(
286                     "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(param));
287         }
288         break;
289         case kAudioSendRtpHeaderExtension:
290         {
291             std::list<RtpHeaderExtension>* listExtension = new std::list<RtpHeaderExtension>();
292             int listSize = parcel.readInt32();
293 
294             for (int32_t i = 0; i < listSize; i++)
295             {
296                 RtpHeaderExtension extension;
297 
298                 if (extension.readFromParcel(&parcel) == NO_ERROR)
299                 {
300                     listExtension->push_back(extension);
301                 }
302             }
303 
304             ImsMediaEventHandler::SendEvent("AUDIO_REQUEST_EVENT", nMsg, sessionId,
305                     reinterpret_cast<uint64_t>(listExtension));
306         }
307         break;
308         case kAudioSetMediaQualityThreshold:
309         {
310             MediaQualityThreshold* threshold = new MediaQualityThreshold();
311             threshold->readFromParcel(&parcel);
312             ImsMediaEventHandler::SendEvent(
313                     "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast<uint64_t>(threshold));
314         }
315         break;
316         default:
317             break;
318     }
319 }
320 
processEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)321 void AudioManager::RequestHandler::processEvent(
322         uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
323 {
324     IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
325             paramA, paramB);
326     ImsMediaResult result = RESULT_SUCCESS;
327 
328     if (sManager == nullptr)
329     {
330         IMLOGE0("[processEvent] not ready");
331         return;
332     }
333 
334     switch (event)
335     {
336         case kAudioOpenSession:
337         {
338             EventParamOpenSession* param = reinterpret_cast<EventParamOpenSession*>(paramA);
339             if (param != nullptr)
340             {
341                 AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(param->mConfig);
342                 result = sManager->openSession(
343                         static_cast<int>(sessionId), param->rtpFd, param->rtcpFd, pConfig);
344 
345                 if (result == RESULT_SUCCESS)
346                 {
347                     ImsMediaEventHandler::SendEvent(
348                             "AUDIO_RESPONSE_EVENT", kAudioOpenSessionSuccess, sessionId);
349                 }
350                 else
351                 {
352                     ImsMediaEventHandler::SendEvent(
353                             "AUDIO_RESPONSE_EVENT", kAudioOpenSessionFailure, sessionId, result);
354                 }
355 
356                 delete param;
357 
358                 if (pConfig != nullptr)
359                 {
360                     delete pConfig;
361                 }
362             }
363             else
364             {
365                 ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioOpenSessionFailure,
366                         sessionId, RESULT_INVALID_PARAM);
367             }
368         }
369         break;
370         case kAudioCloseSession:
371             if (sManager->closeSession(static_cast<int>(sessionId)) == RESULT_SUCCESS)
372             {
373                 ImsMediaEventHandler::SendEvent(
374                         "AUDIO_RESPONSE_EVENT", kAudioSessionClosed, sessionId, 0, 0);
375             }
376             break;
377         case kAudioModifySession:
378         {
379             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramA);
380             result = sManager->modifySession(static_cast<int>(sessionId), config);
381             ImsMediaEventHandler::SendEvent(
382                     "AUDIO_RESPONSE_EVENT", kAudioModifySessionResponse, sessionId, result, paramA);
383         }
384         break;
385         case kAudioAddConfig:
386         {
387             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramA);
388             result = sManager->addConfig(static_cast<int>(sessionId), config);
389             ImsMediaEventHandler::SendEvent(
390                     "AUDIO_RESPONSE_EVENT", kAudioAddConfigResponse, sessionId, result, paramA);
391         }
392         break;
393         case kAudioConfirmConfig:
394         {
395             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramA);
396             result = sManager->confirmConfig(static_cast<int>(sessionId), config);
397             ImsMediaEventHandler::SendEvent(
398                     "AUDIO_RESPONSE_EVENT", kAudioConfirmConfigResponse, sessionId, result, paramA);
399         }
400         break;
401         case kAudioDeleteConfig:
402         {
403             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramA);
404             if (config != nullptr)
405             {
406                 sManager->deleteConfig(static_cast<int>(sessionId), config);
407                 delete config;
408             }
409         }
410         break;
411         case kAudioSendDtmf:
412         {
413             EventParamDtmf* param = reinterpret_cast<EventParamDtmf*>(paramA);
414             if (param != nullptr)
415             {
416                 sManager->sendDtmf(static_cast<int>(sessionId), param->digit, param->duration);
417                 delete param;
418             }
419         }
420         break;
421         case kAudioSendRtpHeaderExtension:
422         {
423             std::list<RtpHeaderExtension>* listExtension =
424                     reinterpret_cast<std::list<RtpHeaderExtension>*>(paramA);
425 
426             if (listExtension != nullptr)
427             {
428                 sManager->sendRtpHeaderExtension(static_cast<int>(sessionId), listExtension);
429                 delete listExtension;
430             }
431         }
432         break;
433         case kAudioSetMediaQualityThreshold:
434         {
435             MediaQualityThreshold* threshold = reinterpret_cast<MediaQualityThreshold*>(paramA);
436             if (threshold != nullptr)
437             {
438                 sManager->setMediaQualityThreshold(static_cast<int>(sessionId), threshold);
439                 delete threshold;
440             }
441         }
442         break;
443         case kRequestAudioCmr:
444         case kRequestAudioCmrEvs:
445         case kRequestSendRtcpXrReport:
446             sManager->SendInternalEvent(event, static_cast<int>(sessionId), paramA, paramB);
447             break;
448         default:
449             break;
450     }
451 }
452 
processEvent(uint32_t event,uint64_t sessionId,uint64_t paramA,uint64_t paramB)453 void AudioManager::ResponseHandler::processEvent(
454         uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB)
455 {
456     IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId,
457             paramA, paramB);
458 
459     if (sManager == nullptr)
460     {
461         IMLOGE0("[processEvent] not ready");
462         return;
463     }
464 
465     android::Parcel parcel;
466     switch (event)
467     {
468         case kAudioOpenSessionSuccess:
469         case kAudioOpenSessionFailure:
470             parcel.writeInt32(event);
471             parcel.writeInt32(static_cast<int>(sessionId));
472             if (event == kAudioOpenSessionFailure)
473             {
474                 // fail reason
475                 parcel.writeInt32(static_cast<int>(paramA));
476             }
477             sManager->sendResponse(sessionId, parcel);
478             break;
479         case kAudioModifySessionResponse:  // fall through
480         case kAudioAddConfigResponse:      // fall through
481         case kAudioConfirmConfigResponse:
482         {
483             parcel.writeInt32(event);
484             parcel.writeInt32(paramA);  // result
485             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramB);
486             if (config != nullptr)
487             {
488                 config->writeToParcel(&parcel);
489                 sManager->sendResponse(sessionId, parcel);
490                 delete config;
491             }
492         }
493         break;
494         case kAudioFirstMediaPacketInd:
495         {
496             parcel.writeInt32(event);
497             AudioConfig* config = reinterpret_cast<AudioConfig*>(paramA);
498             if (config != nullptr)
499             {
500                 config->writeToParcel(&parcel);
501                 sManager->sendResponse(sessionId, parcel);
502                 delete config;
503             }
504         }
505         break;
506         case kAudioRtpHeaderExtensionInd:
507         {
508             parcel.writeInt32(event);
509             std::list<RtpHeaderExtension>* listExtension =
510                     reinterpret_cast<std::list<RtpHeaderExtension>*>(paramA);
511 
512             if (listExtension != nullptr)
513             {
514                 parcel.writeInt32(listExtension->size());
515 
516                 for (auto& extension : *listExtension)
517                 {
518                     extension.writeToParcel(&parcel);
519                 }
520 
521                 sManager->sendResponse(sessionId, parcel);
522                 delete listExtension;
523             }
524         }
525         break;
526         case kAudioMediaQualityStatusInd:
527         {
528             parcel.writeInt32(event);
529             MediaQualityStatus* status = reinterpret_cast<MediaQualityStatus*>(paramA);
530             if (status != nullptr)
531             {
532                 status->writeToParcel(&parcel);
533                 sManager->sendResponse(sessionId, parcel);
534                 delete status;
535             }
536         }
537         break;
538         case kAudioTriggerAnbrQueryInd:
539             /** TODO: add implementation */
540             break;
541         case kAudioDtmfReceivedInd:
542             parcel.writeInt32(event);
543             parcel.writeByte(static_cast<uint8_t>(paramA));
544             parcel.writeInt32(static_cast<int>(paramB));
545             sManager->sendResponse(sessionId, parcel);
546             break;
547         case kAudioCallQualityChangedInd:
548         {
549             parcel.writeInt32(event);
550             CallQuality* quality = reinterpret_cast<CallQuality*>(paramA);
551             if (quality != nullptr)
552             {
553                 quality->writeToParcel(&parcel);
554                 sManager->sendResponse(sessionId, parcel);
555                 delete quality;
556             }
557         }
558         break;
559         case kAudioSessionClosed:
560             parcel.writeInt32(event);
561             parcel.writeInt32(static_cast<int>(sessionId));
562             sManager->sendResponse(sessionId, parcel);
563             break;
564         default:
565             break;
566     }
567 }
568 
isOtherSessionActive(const int sessionId)569 bool AudioManager::isOtherSessionActive(const int sessionId)
570 {
571     for (auto const& session : mSessions)
572     {
573         if (session.first != sessionId)
574         {
575             SessionState state = (session.second)->getState();
576             if (state == kSessionStateActive || state == kSessionStateReceiving ||
577                     state == kSessionStateSending)
578             {
579                 IMLOGE1("[modifySession] Another session id[%d] is active", session.first);
580                 return true;
581             }
582         }
583     }
584     return false;
585 }
586