/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include using namespace android; AudioManager* AudioManager::sManager = nullptr; AudioManager::AudioManager() {} AudioManager::~AudioManager() {} AudioManager* AudioManager::getInstance() { if (sManager == nullptr) { sManager = new AudioManager(); } return sManager; } int AudioManager::getState(int sessionId) { auto session = mSessions.find(sessionId); if (session != mSessions.end()) { return (session->second)->getState(); } else { return kSessionStateClosed; } } ImsMediaResult AudioManager::openSession(int sessionId, int rtpFd, int rtcpFd, AudioConfig* config) { IMLOGI1("[openSession] sessionId[%d]", sessionId); if (rtpFd == -1 || rtcpFd == -1) { return RESULT_INVALID_PARAM; } if (!mSessions.count(sessionId)) { std::unique_ptr session(new AudioSession()); session->setSessionId(sessionId); session->setLocalEndPoint(rtpFd, rtcpFd); if (session->startGraph(config) != RESULT_SUCCESS) { IMLOGI0("[openSession] startGraph failed"); } mSessions.insert(std::make_pair(sessionId, std::move(session))); } else { return RESULT_INVALID_PARAM; } return RESULT_SUCCESS; } ImsMediaResult AudioManager::closeSession(int sessionId) { IMLOGI1("[closeSession] sessionId[%d]", sessionId); if (mSessions.count(sessionId)) { mSessions.erase(sessionId); return RESULT_SUCCESS; } return RESULT_INVALID_PARAM; } ImsMediaResult AudioManager::modifySession(int sessionId, AudioConfig* config) { auto session = mSessions.find(sessionId); IMLOGI1("[modifySession] sessionId[%d]", sessionId); if (session != mSessions.end()) { if ((session->second)->IsGraphAlreadyExist(config) || (session->second)->getGraphSize(kStreamRtpTx) == 0) { return (session->second)->startGraph(config); } else { return (session->second)->addGraph(config, false); } } else { IMLOGE1("[modifySession] no session id[%d]", sessionId); return RESULT_INVALID_PARAM; } } ImsMediaResult AudioManager::addConfig(int sessionId, AudioConfig* config) { auto session = mSessions.find(sessionId); IMLOGI1("[addConfig] sessionId[%d]", sessionId); if (session != mSessions.end()) { return (session->second)->addGraph(config, true); } else { IMLOGE1("[addConfig] no session id[%d]", sessionId); return RESULT_INVALID_PARAM; } } ImsMediaResult AudioManager::deleteConfig(int sessionId, AudioConfig* config) { auto session = mSessions.find(sessionId); IMLOGI1("[deleteConfig] sessionId[%d]", sessionId); if (session != mSessions.end()) { return (session->second)->deleteGraph(config); } else { IMLOGE1("[deleteConfig] no session id[%d]", sessionId); return RESULT_INVALID_PARAM; } } ImsMediaResult AudioManager::confirmConfig(int sessionId, AudioConfig* config) { auto session = mSessions.find(sessionId); IMLOGI1("[confirmConfig] sessionId[%d]", sessionId); if (session != mSessions.end()) { return (session->second)->confirmGraph(config); } else { IMLOGE1("[confirmConfig] no session id[%d]", sessionId); return RESULT_INVALID_PARAM; } } void AudioManager::sendDtmf(int sessionId, char dtmfDigit, int duration) { auto session = mSessions.find(sessionId); IMLOGI1("[sendDtmf] sessionId[%d]", sessionId); if (session != mSessions.end()) { (session->second)->sendDtmf(dtmfDigit, duration); } else { IMLOGE1("[sendDtmf] no session id[%d]", sessionId); } } void AudioManager::sendRtpHeaderExtension( int sessionId, std::list* listExtension) { auto session = mSessions.find(sessionId); IMLOGI1("[sendRtpHeaderExtension] sessionId[%d]", sessionId); if (session != mSessions.end()) { (session->second)->sendRtpHeaderExtension(listExtension); } else { IMLOGE1("[sendRtpHeaderExtension] no session id[%d]", sessionId); } } void AudioManager::setMediaQualityThreshold(int sessionId, MediaQualityThreshold* threshold) { auto session = mSessions.find(sessionId); IMLOGI1("[setMediaQualityThreshold] sessionId[%d]", sessionId); if (session != mSessions.end()) { (session->second)->setMediaQualityThreshold(*threshold); } else { IMLOGE1("[setMediaQualityThreshold] no session id[%d]", sessionId); } } void AudioManager::sendMessage(const int sessionId, const android::Parcel& parcel) { int nMsg = parcel.readInt32(); status_t err = NO_ERROR; switch (nMsg) { case kAudioOpenSession: { int rtpFd = parcel.readInt32(); int rtcpFd = parcel.readInt32(); AudioConfig* config = new AudioConfig(); err = config->readFromParcel(&parcel); if (err != NO_ERROR && err != -ENODATA) { IMLOGE1("[sendMessage] error readFromParcel[%d]", err); } EventParamOpenSession* param = new EventParamOpenSession(rtpFd, rtcpFd, config); ImsMediaEventHandler::SendEvent( "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast(param)); } break; case kAudioCloseSession: ImsMediaEventHandler::SendEvent("AUDIO_REQUEST_EVENT", nMsg, sessionId); break; case kAudioModifySession: case kAudioAddConfig: case kAudioConfirmConfig: case kAudioDeleteConfig: { AudioConfig* config = new AudioConfig(); err = config->readFromParcel(&parcel); if (err != NO_ERROR) { IMLOGE1("[sendMessage] error readFromParcel[%d]", err); } ImsMediaEventHandler::SendEvent( "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast(config)); } break; case kAudioSendDtmf: { EventParamDtmf* param = new EventParamDtmf(parcel.readByte(), parcel.readInt32()); ImsMediaEventHandler::SendEvent( "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast(param)); } break; case kAudioSendRtpHeaderExtension: { std::list* listExtension = new std::list(); int listSize = parcel.readInt32(); for (int32_t i = 0; i < listSize; i++) { RtpHeaderExtension extension; if (extension.readFromParcel(&parcel) == NO_ERROR) { listExtension->push_back(extension); } } ImsMediaEventHandler::SendEvent("AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast(listExtension)); } break; case kAudioSetMediaQualityThreshold: { MediaQualityThreshold* threshold = new MediaQualityThreshold(); threshold->readFromParcel(&parcel); ImsMediaEventHandler::SendEvent( "AUDIO_REQUEST_EVENT", nMsg, sessionId, reinterpret_cast(threshold)); } break; default: break; } } void AudioManager::SendInternalEvent( uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB) { auto session = mSessions.find(sessionId); IMLOGI1("[SendInternalEvent] sessionId[%d]", sessionId); if (session != mSessions.end()) { (session->second)->SendInternalEvent(event, paramA, paramB); } else { IMLOGE1("[SendInternalEvent] no session id[%d]", sessionId); } } AudioManager::RequestHandler::RequestHandler() : ImsMediaEventHandler("AUDIO_REQUEST_EVENT") { } AudioManager::RequestHandler::~RequestHandler() {} void AudioManager::RequestHandler::processEvent( uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB) { IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId, paramA, paramB); ImsMediaResult result = RESULT_SUCCESS; switch (event) { case kAudioOpenSession: { EventParamOpenSession* param = reinterpret_cast(paramA); if (param != nullptr) { AudioConfig* pConfig = reinterpret_cast(param->mConfig); result = AudioManager::getInstance()->openSession( static_cast(sessionId), param->rtpFd, param->rtcpFd, pConfig); if (result == RESULT_SUCCESS) { ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioOpenSessionSuccess, sessionId); } else { ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioOpenSessionFailure, sessionId, result); } delete param; if (pConfig != nullptr) { delete pConfig; } } else { ImsMediaEventHandler::SendEvent("AUDIO_RESPONSE_EVENT", kAudioOpenSessionFailure, sessionId, RESULT_INVALID_PARAM); } } break; case kAudioCloseSession: if (AudioManager::getInstance()->closeSession(static_cast(sessionId)) == RESULT_SUCCESS) { ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioSessionClosed, sessionId, 0, 0); } break; case kAudioModifySession: { AudioConfig* config = reinterpret_cast(paramA); result = AudioManager::getInstance()->modifySession(static_cast(sessionId), config); ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioModifySessionResponse, sessionId, result, paramA); } break; case kAudioAddConfig: { AudioConfig* config = reinterpret_cast(paramA); result = AudioManager::getInstance()->addConfig(static_cast(sessionId), config); ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioAddConfigResponse, sessionId, result, paramA); } break; case kAudioConfirmConfig: { AudioConfig* config = reinterpret_cast(paramA); result = AudioManager::getInstance()->confirmConfig(static_cast(sessionId), config); ImsMediaEventHandler::SendEvent( "AUDIO_RESPONSE_EVENT", kAudioConfirmConfigResponse, sessionId, result, paramA); } break; case kAudioDeleteConfig: { AudioConfig* config = reinterpret_cast(paramA); if (config != nullptr) { AudioManager::getInstance()->deleteConfig(static_cast(sessionId), config); delete config; } } break; case kAudioSendDtmf: { EventParamDtmf* param = reinterpret_cast(paramA); if (param != nullptr) { AudioManager::getInstance()->sendDtmf( static_cast(sessionId), param->digit, param->duration); delete param; } } break; case kAudioSendRtpHeaderExtension: { std::list* listExtension = reinterpret_cast*>(paramA); if (listExtension != nullptr) { AudioManager::getInstance()->sendRtpHeaderExtension( static_cast(sessionId), listExtension); delete listExtension; } } break; case kAudioSetMediaQualityThreshold: { MediaQualityThreshold* threshold = reinterpret_cast(paramA); if (threshold != nullptr) { AudioManager::getInstance()->setMediaQualityThreshold( static_cast(sessionId), threshold); delete threshold; } } break; case kRequestAudioCmr: case kRequestSendRtcpXrReport: AudioManager::getInstance()->SendInternalEvent( event, static_cast(sessionId), paramA, paramB); break; default: break; } } AudioManager::ResponseHandler::ResponseHandler() : ImsMediaEventHandler("AUDIO_RESPONSE_EVENT") { } AudioManager::ResponseHandler::~ResponseHandler() {} void AudioManager::ResponseHandler::processEvent( uint32_t event, uint64_t sessionId, uint64_t paramA, uint64_t paramB) { IMLOGI4("[processEvent] event[%d], sessionId[%d], paramA[%d], paramB[%d]", event, sessionId, paramA, paramB); android::Parcel parcel; switch (event) { case kAudioOpenSessionSuccess: case kAudioOpenSessionFailure: parcel.writeInt32(event); parcel.writeInt32(static_cast(sessionId)); if (event == kAudioOpenSessionFailure) { // fail reason parcel.writeInt32(static_cast(paramA)); } AudioManager::getInstance()->sendResponse(sessionId, parcel); break; case kAudioModifySessionResponse: // fall through case kAudioAddConfigResponse: // fall through case kAudioConfirmConfigResponse: { parcel.writeInt32(event); parcel.writeInt32(paramA); // result AudioConfig* config = reinterpret_cast(paramB); if (config != nullptr) { config->writeToParcel(&parcel); AudioManager::getInstance()->sendResponse(sessionId, parcel); delete config; } } break; case kAudioFirstMediaPacketInd: { parcel.writeInt32(event); AudioConfig* config = reinterpret_cast(paramA); if (config != nullptr) { config->writeToParcel(&parcel); AudioManager::getInstance()->sendResponse(sessionId, parcel); delete config; } } break; case kAudioRtpHeaderExtensionInd: { parcel.writeInt32(event); std::list* listExtension = reinterpret_cast*>(paramA); if (listExtension != nullptr) { parcel.writeInt32(listExtension->size()); for (auto& extension : *listExtension) { extension.writeToParcel(&parcel); } AudioManager::getInstance()->sendResponse(sessionId, parcel); delete listExtension; } } break; case kAudioMediaQualityStatusInd: { parcel.writeInt32(event); MediaQualityStatus* status = reinterpret_cast(paramA); if (status != nullptr) { status->writeToParcel(&parcel); AudioManager::getInstance()->sendResponse(sessionId, parcel); delete status; } } break; case kAudioTriggerAnbrQueryInd: /** TODO: add implementation */ break; case kAudioDtmfReceivedInd: parcel.writeInt32(event); parcel.writeByte(static_cast(paramA)); parcel.writeInt32(static_cast(paramB)); AudioManager::getInstance()->sendResponse(sessionId, parcel); break; case kAudioCallQualityChangedInd: { parcel.writeInt32(event); CallQuality* quality = reinterpret_cast(paramA); if (quality != nullptr) { quality->writeToParcel(&parcel); AudioManager::getInstance()->sendResponse(sessionId, parcel); delete quality; } } break; case kAudioSessionClosed: parcel.writeInt32(event); parcel.writeInt32(static_cast(sessionId)); AudioManager::getInstance()->sendResponse(sessionId, parcel); break; default: break; } }