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