summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBodam Nam <bodamnam@google.com>2023-02-15 02:30:02 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-02-15 02:30:02 +0000
commitb571b0c282de387f3b246d5bb292b2aa3bb078df (patch)
treef21b838def0f83df4a8d395294accd66453e53e9
parent3b00831d6479da84cab69b529c085d94e795e224 (diff)
parent3a1bf17f69890421dfca05c35cf5a8debcf79c55 (diff)
downloadImsMedia-b571b0c282de387f3b246d5bb292b2aa3bb078df.tar.gz
Merge "Modify AudioSession to delete old stream when modifySession is called with new remote address."
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp3
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp294
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpRx.cpp21
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp22
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h6
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h8
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraph.h8
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpRx.h1
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h1
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSessionTest.cpp337
10 files changed, 495 insertions, 206 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
index faabe4fc..357a1d71 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioManager.cpp
@@ -97,7 +97,8 @@ ImsMediaResult AudioManager::modifySession(int sessionId, AudioConfig* config)
IMLOGI1("[modifySession] sessionId[%d]", sessionId);
if (session != mSessions.end())
{
- if ((session->second)->IsGraphAlreadyExist(config))
+ if ((session->second)->IsGraphAlreadyExist(config) ||
+ (session->second)->getGraphSize(kStreamRtpTx) == 0)
{
return (session->second)->startGraph(config);
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
index b2bb681b..e17112f6 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
@@ -18,9 +18,7 @@
#include <ImsMediaTrace.h>
#include <ImsMediaEventHandler.h>
#include <ImsMediaAudioUtil.h>
-
#include <AudioConfig.h>
-
#include <string>
AudioSession::AudioSession()
@@ -85,7 +83,8 @@ SessionState AudioSession::getState()
{
if (graph != nullptr && graph->getState() == kStreamStateRunning)
{
- return kSessionStateActive;
+ state = kSessionStateSending;
+ break;
}
}
@@ -93,7 +92,7 @@ SessionState AudioSession::getState()
{
if (graph != nullptr && graph->getState() == kStreamStateRunning)
{
- return kSessionStateActive;
+ return state == kSessionStateSending ? kSessionStateActive : kSessionStateReceiving;
}
}
@@ -101,7 +100,7 @@ SessionState AudioSession::getState()
{
if (graph != nullptr && graph->getState() == kStreamStateRunning)
{
- return kSessionStateSuspended;
+ return state == kSessionStateSending ? kSessionStateSending : kSessionStateSuspended;
}
}
@@ -127,16 +126,15 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
ImsMediaResult ret = RESULT_NOT_READY;
IMLOGD1("[startGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
- if (mListGraphRtpTx.size() != 0)
- {
- for (auto& graph : mListGraphRtpTx)
- {
- if (graph != nullptr && graph->isSameGraph(config))
+ AudioStreamGraphRtpTx* graphTx = AudioStreamGraph::findGraph(mListGraphRtpTx,
+ [&config](AudioStreamGraphRtpTx* graph)
{
- ret = graph->update(config);
- break;
- }
- }
+ return graph != nullptr && graph->isSameGraph(config);
+ });
+
+ if (graphTx != nullptr)
+ {
+ ret = graphTx->update(config);
if (ret != RESULT_SUCCESS)
{
@@ -147,13 +145,11 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
else
{
mListGraphRtpTx.push_back(new AudioStreamGraphRtpTx(this, mRtpFd));
- ret = mListGraphRtpTx.back()->create(config);
- if (ret == RESULT_SUCCESS &&
- (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
- pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE))
+ if (mListGraphRtpTx.back()->create(config) == RESULT_SUCCESS)
{
ret = mListGraphRtpTx.back()->start();
+
if (ret != RESULT_SUCCESS)
{
IMLOGE1("[startGraph] start error[%d]", ret);
@@ -162,19 +158,18 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
}
}
- IMLOGD1("[startGraph] mListGraphRtpRx size[%d]", mListGraphRtpRx.size());
+ IMLOGD1("[startGraph] ListGraphRtpRx size[%d]", mListGraphRtpRx.size());
- if (mListGraphRtpRx.size() != 0)
- {
- for (auto& graph : mListGraphRtpRx)
- {
- if (graph != nullptr && graph->isSameGraph(config))
+ AudioStreamGraphRtpRx* graphRx = AudioStreamGraph::findGraph(mListGraphRtpRx,
+ [&config](AudioStreamGraphRtpRx* graph)
{
- graph->setMediaQualityThreshold(&mThreshold);
- ret = graph->update(config);
- break;
- }
- }
+ return graph != nullptr && graph->isSameGraph(config);
+ });
+
+ if (graphRx != nullptr)
+ {
+ graphRx->setMediaQualityThreshold(&mThreshold);
+ ret = graphRx->update(config);
if (ret != RESULT_SUCCESS)
{
@@ -185,11 +180,8 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
else
{
mListGraphRtpRx.push_back(new AudioStreamGraphRtpRx(this, mRtpFd));
- ret = mListGraphRtpRx.back()->create(config);
- if (ret == RESULT_SUCCESS &&
- (pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
- pConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE))
+ if (mListGraphRtpRx.back()->create(config) == RESULT_SUCCESS)
{
mListGraphRtpRx.back()->setMediaQualityThreshold(&mThreshold);
ret = mListGraphRtpRx.back()->start();
@@ -204,17 +196,16 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
IMLOGD1("[startGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
- if (mListGraphRtcp.size() != 0)
- {
- for (auto& graph : mListGraphRtcp)
- {
- if (graph != nullptr && graph->isSameGraph(config))
+ AudioStreamGraphRtcp* graphRtcp = AudioStreamGraph::findGraph(mListGraphRtcp,
+ [&config](AudioStreamGraphRtcp* graph)
{
- graph->setMediaQualityThreshold(&mThreshold);
- ret = graph->update(config);
- break;
- }
- }
+ return graph != nullptr && graph->isSameGraph(config);
+ });
+
+ if (graphRtcp != nullptr)
+ {
+ graphRtcp->setMediaQualityThreshold(&mThreshold);
+ ret = graphRtcp->update(config);
if (ret != RESULT_SUCCESS)
{
@@ -225,12 +216,12 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
else
{
mListGraphRtcp.push_back(new AudioStreamGraphRtcp(this, mRtcpFd));
- ret = mListGraphRtcp.back()->create(config);
- if (ret == RESULT_SUCCESS)
+ if (mListGraphRtcp.back()->create(config) == RESULT_SUCCESS)
{
mListGraphRtcp.back()->setMediaQualityThreshold(&mThreshold);
ret = mListGraphRtcp.back()->start();
+
if (ret != RESULT_SUCCESS)
{
IMLOGE1("[startGraph] start error[%d]", ret);
@@ -262,97 +253,43 @@ ImsMediaResult AudioSession::addGraph(RtpConfig* config, bool enableRtcp)
return RESULT_INVALID_PARAM;
}
- for (auto& graph : mListGraphRtpTx)
- {
- if (graph != nullptr && graph->isSameGraph(config))
- {
- IMLOGW0("[addGraph] same config is exist");
- return startGraph(config);
- }
- }
-
- for (auto& graph : mListGraphRtpTx)
+ if (IsGraphAlreadyExist(config) || mListGraphRtpTx.empty())
{
- if (graph != nullptr)
- {
- graph->stop();
- }
+ return startGraph(config);
}
- for (auto& graph : mListGraphRtpRx)
+ if (enableRtcp) // update current graph to inactive mode
{
- if (graph != nullptr)
+ for (auto& graph : mListGraphRtpTx)
{
- graph->stop();
+ if (graph != nullptr)
+ {
+ graph->stop();
+ }
}
- }
- for (auto& graph : mListGraphRtcp)
- {
- if (graph != nullptr && graph->getState() != kStreamStateRunning)
+ for (auto& graph : mListGraphRtpRx)
{
- enableRtcp ? graph->start() : graph->stop();
+ if (graph != nullptr)
+ {
+ graph->stop();
+ }
}
- }
-
- ImsMediaResult ret = RESULT_NOT_READY;
-
- mListGraphRtpTx.push_back(new AudioStreamGraphRtpTx(this, mRtpFd));
- ret = mListGraphRtpTx.back()->create(config);
- if (ret == RESULT_SUCCESS)
- {
- ret = mListGraphRtpTx.back()->start();
- if (ret != RESULT_SUCCESS)
+ for (auto& graph : mListGraphRtcp)
{
- IMLOGE1("[addGraph] start error[%d]", ret);
- return ret;
+ if (graph != nullptr && graph->getState() != kStreamStateRunning)
+ {
+ graph->start();
+ }
}
- }
-
- IMLOGD1("[addGraph] mListGraphTx size[%d]", mListGraphRtpTx.size());
-
- mListGraphRtpRx.push_back(new AudioStreamGraphRtpRx(this, mRtpFd));
- ret = mListGraphRtpRx.back()->create(config);
- if (ret == RESULT_SUCCESS)
- {
- mListGraphRtpRx.back()->setMediaQualityThreshold(&mThreshold);
- ret = mListGraphRtpRx.back()->start();
- if (ret != RESULT_SUCCESS)
- {
- IMLOGE1("[addGraph] start error[%d]", ret);
- return ret;
- }
+ return startGraph(config);
}
-
- IMLOGD1("[addGraph] mListGraphRx size[%d]", mListGraphRtpRx.size());
-
- mListGraphRtcp.push_back(new AudioStreamGraphRtcp(this, mRtcpFd));
- ret = mListGraphRtcp.back()->create(config);
-
- if (ret == RESULT_SUCCESS)
+ else
{
- mListGraphRtcp.back()->setMediaQualityThreshold(&mThreshold);
- ret = mListGraphRtcp.back()->start();
- if (ret != RESULT_SUCCESS)
- {
- IMLOGE1("[addGraph] start error[%d]", ret);
- return ret;
- }
+ return confirmGraph(config);
}
-
- IMLOGD1("[addGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
-
- if (mMediaQualityAnalyzer != nullptr &&
- !mMediaQualityAnalyzer->isSameConfig(reinterpret_cast<AudioConfig*>(config)))
- {
- mMediaQualityAnalyzer->stop();
- mMediaQualityAnalyzer->setConfig(reinterpret_cast<AudioConfig*>(config));
- mMediaQualityAnalyzer->start();
- }
-
- return RESULT_SUCCESS;
}
ImsMediaResult AudioSession::confirmGraph(RtpConfig* config)
@@ -362,99 +299,44 @@ ImsMediaResult AudioSession::confirmGraph(RtpConfig* config)
return RESULT_INVALID_PARAM;
}
- ImsMediaResult ret = RESULT_NOT_READY;
-
- /** Stop unmatched running instances of StreamGraph. */
- for (auto& graph : mListGraphRtpTx)
- {
- if (graph != nullptr && !graph->isSameGraph(config))
- {
- graph->stop();
- }
- }
-
- for (auto& graph : mListGraphRtpRx)
+ if (mListGraphRtpTx.empty() || mListGraphRtpRx.empty() || mListGraphRtcp.empty())
{
- if (graph != nullptr && !graph->isSameGraph(config))
- {
- graph->stop();
- }
+ return startGraph(config);
}
- for (auto& graph : mListGraphRtcp)
- {
- if (graph != nullptr && !graph->isSameGraph(config))
- {
- graph->stop();
- }
- }
-
- bool bFound = false;
+ /** Stop and delete unmatched running instances of StreamGraph. */
for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
iter != mListGraphRtpTx.end();)
{
AudioStreamGraphRtpTx* graph = *iter;
- if (graph == nullptr)
- {
- continue;
- }
-
- if (!graph->isSameGraph(config))
+ if (graph != nullptr && !graph->isSameGraph(config))
{
+ graph->stop();
iter = mListGraphRtpTx.erase(iter);
delete graph;
}
else
{
- if (graph->getState() != kStreamStateRunning)
- {
- ret = graph->start();
- if (ret != RESULT_SUCCESS)
- {
- IMLOGE1("[confirmGraph] start tx error[%d]", ret);
- return ret;
- }
- }
iter++;
- bFound = true;
}
}
IMLOGD1("[confirmGraph] mListGraphTx size[%d]", mListGraphRtpTx.size());
- if (bFound == false)
- {
- IMLOGE0("[confirmGraph] no graph to confirm");
- return RESULT_INVALID_PARAM;
- }
-
for (std::list<AudioStreamGraphRtpRx*>::iterator iter = mListGraphRtpRx.begin();
iter != mListGraphRtpRx.end();)
{
AudioStreamGraphRtpRx* graph = *iter;
- if (graph == nullptr)
- {
- continue;
- }
-
- if (!graph->isSameGraph(config))
+ if (graph != nullptr && !graph->isSameGraph(config))
{
+ graph->stop();
iter = mListGraphRtpRx.erase(iter);
delete graph;
}
else
{
- if (graph->getState() != kStreamStateRunning)
- {
- ret = graph->start();
- if (ret != RESULT_SUCCESS)
- {
- IMLOGE1("[confirmGraph] start rx error[%d]", ret);
- return ret;
- }
- }
iter++;
}
}
@@ -466,35 +348,21 @@ ImsMediaResult AudioSession::confirmGraph(RtpConfig* config)
{
AudioStreamGraphRtcp* graph = *iter;
- if (graph == nullptr)
- {
- continue;
- }
-
- if (!graph->isSameGraph(config))
+ if (graph != nullptr && !graph->isSameGraph(config))
{
+ graph->stop();
iter = mListGraphRtcp.erase(iter);
delete graph;
}
else
{
- if (graph->getState() != kStreamStateRunning)
- {
- ret = graph->start();
- if (ret != RESULT_SUCCESS)
- {
- IMLOGE1("[confirmGraph] start rtcp error[%d]", ret);
- return ret;
- }
- }
-
iter++;
}
}
IMLOGD1("[confirmGraph] mListGraphRtcp size[%d]", mListGraphRtcp.size());
- return RESULT_SUCCESS;
+ return startGraph(config);
}
ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
@@ -514,11 +382,7 @@ ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
if (graph->isSameGraph(config))
{
- if (graph->getState() == kStreamStateRunning)
- {
- graph->stop();
- }
-
+ graph->stop();
iter = mListGraphRtpTx.erase(iter);
delete graph;
bFound = true;
@@ -553,6 +417,7 @@ ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
{
graph->stop();
}
+
iter = mListGraphRtpRx.erase(iter);
delete graph;
break;
@@ -581,6 +446,7 @@ ImsMediaResult AudioSession::deleteGraph(RtpConfig* config)
{
graph->stop();
}
+
iter = mListGraphRtcp.erase(iter);
delete graph;
break;
@@ -664,6 +530,11 @@ void AudioSession::setMediaQualityThreshold(const MediaQualityThreshold& thresho
void AudioSession::sendDtmf(char digit, int duration)
{
+ if (mListGraphRtpTx.empty())
+ {
+ return;
+ }
+
for (std::list<AudioStreamGraphRtpTx*>::iterator iter = mListGraphRtpTx.begin();
iter != mListGraphRtpTx.end(); iter++)
{
@@ -692,6 +563,21 @@ bool AudioSession::IsGraphAlreadyExist(RtpConfig* config)
return false;
}
+uint32_t AudioSession::getGraphSize(ImsMediaStreamType type)
+{
+ switch (type)
+ {
+ case kStreamRtpTx:
+ return mListGraphRtpTx.size();
+ case kStreamRtpRx:
+ return mListGraphRtpRx.size();
+ case kStreamRtcp:
+ return mListGraphRtcp.size();
+ }
+
+ return 0;
+}
+
void AudioSession::SendInternalEvent(int32_t type, uint64_t param1, uint64_t param2)
{
(void)param2;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpRx.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpRx.cpp
index d3d0d791..70963147 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpRx.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpRx.cpp
@@ -106,15 +106,18 @@ ImsMediaResult AudioStreamGraphRtpRx::update(RtpConfig* config)
IMLOGI0("[update] pause RX");
return stop();
}
+
ImsMediaResult ret = RESULT_NOT_READY;
if (mGraphState == kStreamStateRunning)
{
mScheduler->Stop();
+
for (auto& node : mListNodeStarted)
{
IMLOGD1("[update] update node[%s]", node->GetNodeName());
ret = node->UpdateConfig(mConfig);
+
if (ret != RESULT_SUCCESS)
{
IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
@@ -128,6 +131,7 @@ ImsMediaResult AudioStreamGraphRtpRx::update(RtpConfig* config)
{
IMLOGD1("[update] update node[%s]", node->GetNodeName());
ret = node->UpdateConfig(mConfig);
+
if (ret != RESULT_SUCCESS)
{
IMLOGE2("[update] error in update node[%s], ret[%d]", node->GetNodeName(), ret);
@@ -144,4 +148,21 @@ ImsMediaResult AudioStreamGraphRtpRx::update(RtpConfig* config)
}
return ret;
+}
+
+ImsMediaResult AudioStreamGraphRtpRx::start()
+{
+ if (mConfig == nullptr)
+ {
+ return RESULT_NOT_READY;
+ }
+
+ if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY ||
+ mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE)
+ {
+ return BaseStreamGraph::start();
+ }
+
+ // not started
+ return RESULT_SUCCESS;
} \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
index 3444ab43..4a991320 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioStreamGraphRtpTx.cpp
@@ -154,6 +154,23 @@ ImsMediaResult AudioStreamGraphRtpTx::update(RtpConfig* config)
return ret;
}
+ImsMediaResult AudioStreamGraphRtpTx::start()
+{
+ if (mConfig == nullptr)
+ {
+ return RESULT_NOT_READY;
+ }
+
+ if (mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_ONLY ||
+ mConfig->getMediaDirection() == RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE)
+ {
+ return BaseStreamGraph::start();
+ }
+
+ // not started
+ return RESULT_SUCCESS;
+}
+
bool AudioStreamGraphRtpTx::createDtmfGraph(RtpConfig* config, BaseNode* rtpEncoderNode)
{
if (config == nullptr)
@@ -168,6 +185,11 @@ bool AudioStreamGraphRtpTx::createDtmfGraph(RtpConfig* config, BaseNode* rtpEnco
return false;
}
+ if (mConfig == nullptr)
+ {
+ mConfig = new AudioConfig(*audioConfig);
+ }
+
BaseNode* pDtmfEncoderNode = new DtmfEncoderNode(mCallback);
pDtmfEncoderNode->SetMediaType(IMS_MEDIA_AUDIO);
pDtmfEncoderNode->SetConfig(audioConfig);
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
index 74699708..9006f64d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
@@ -447,7 +447,11 @@ enum SessionState
{
/** The state that the session is created but graph is not created */
kSessionStateOpened,
- /** The state that the session is created and the Rtp StreamGraphs are running */
+ /** The state that the session is created and the TX rtp StreamGraphs are running */
+ kSessionStateSending,
+ /** The state that the session is created and the RX rtp StreamGraphs are running */
+ kSessionStateReceiving,
+ /** The state that the session is created and the both TX and Rx rtp StreamGraphs are running */
kSessionStateActive,
/** The state that the session is created and the Rtp StreamGraphs is not running */
kSessionStateSuspended,
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
index ce3bd47e..10d8b916 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioSession.h
@@ -95,6 +95,14 @@ public:
*/
bool IsGraphAlreadyExist(RtpConfig* config);
+ /**
+ * @brief Get graph list size with repective stream type
+ *
+ * @param type The graph type to fetch
+ * @return uint32_t The size of list
+ */
+ uint32_t getGraphSize(ImsMediaStreamType type);
+
private:
std::list<AudioStreamGraphRtpTx*> mListGraphRtpTx;
std::list<AudioStreamGraphRtpRx*> mListGraphRtpRx;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraph.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraph.h
index 203ea682..211b981d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraph.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraph.h
@@ -20,6 +20,7 @@
#include <ImsMediaDefine.h>
#include <BaseStreamGraph.h>
#include <AudioConfig.h>
+#include <algorithm> // std::find_if
class AudioStreamGraph : public BaseStreamGraph
{
@@ -49,6 +50,13 @@ public:
mConfig->getRemotePort() == config->getRemotePort());
}
+ template <class T1, class T2>
+ static T1* findGraph(std::list<T1*> list, T2 func)
+ {
+ typename std::list<T1*>::iterator iter = std::find_if(list.begin(), list.end(), func);
+ return iter == list.end() ? nullptr : *iter;
+ }
+
protected:
AudioConfig* mConfig;
};
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpRx.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpRx.h
index cfc9e55f..78e80a82 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpRx.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpRx.h
@@ -27,6 +27,7 @@ public:
virtual ~AudioStreamGraphRtpRx();
virtual ImsMediaResult create(RtpConfig* config);
virtual ImsMediaResult update(RtpConfig* config);
+ virtual ImsMediaResult start();
};
#endif \ No newline at end of file
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
index c042b7c7..753774f1 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioStreamGraphRtpTx.h
@@ -27,6 +27,7 @@ public:
virtual ~AudioStreamGraphRtpTx();
virtual ImsMediaResult create(RtpConfig* config);
virtual ImsMediaResult update(RtpConfig* config);
+ virtual ImsMediaResult start();
/**
* @brief Create a graph for send dtmf digit to network
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSessionTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSessionTest.cpp
new file mode 100644
index 00000000..bd4a6010
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSessionTest.cpp
@@ -0,0 +1,337 @@
+/**
+ * Copyright (C) 2023 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 <gtest/gtest.h>
+#include <ImsMediaNetworkUtil.h>
+#include <AudioConfig.h>
+#include <AudioSession.h>
+
+using namespace android::telephony::imsmedia;
+
+// RtpConfig
+const int32_t kMediaDirection = RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE;
+const android::String8 kRemoteAddress("127.0.0.1");
+const int32_t kRemotePort = 10000;
+const int8_t kDscp = 0;
+const int8_t kRxPayload = 96;
+const int8_t kTxPayload = 96;
+const int8_t kSamplingRate = 16;
+
+// RtcpConfig
+const android::String8 kCanonicalName("name");
+const int32_t kTransmitPort = 1001;
+const int32_t kIntervalSec = 5;
+const int32_t kRtcpXrBlockTypes = RtcpConfig::FLAG_RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK |
+ RtcpConfig::FLAG_RTCPXR_VOIP_METRICS_REPORT_BLOCK;
+
+// AudioConfig
+const int8_t kPTimeMillis = 20;
+const int32_t kMaxPtimeMillis = 100;
+const bool kDtxEnabled = true;
+const int32_t kCodecType = AudioConfig::CODEC_AMR_WB;
+const int8_t kDtmfTxPayloadTypeNumber = 100;
+const int8_t kDtmfRxPayloadTypeNumber = 101;
+const int8_t kDtmfsamplingRateKHz = 16;
+
+// AmrParam
+const int32_t kAmrMode = 8;
+const bool kOctetAligned = false;
+const int32_t kMaxRedundancyMillis = 240;
+
+// EvsParam
+const int32_t kEvsBandwidth = EvsParams::EVS_BAND_NONE;
+const int32_t kEvsMode = 8;
+const int8_t kChannelAwareMode = 3;
+const bool kUseHeaderFullOnly = false;
+const int8_t kcodecModeRequest = 15;
+
+class AudioSessionTest : public ::testing::Test
+{
+public:
+ AudioSession* session;
+ AudioConfig config;
+ RtcpConfig rtcp;
+ AmrParams amr;
+ EvsParams evs;
+ int socketRtpFd;
+ int socketRtcpFd;
+
+ AudioSessionTest()
+ {
+ session = nullptr;
+ socketRtpFd = -1;
+ socketRtcpFd = -1;
+ }
+ ~AudioSessionTest() {}
+
+protected:
+ virtual void SetUp() override
+ {
+ rtcp.setCanonicalName(kCanonicalName);
+ rtcp.setTransmitPort(kTransmitPort);
+ rtcp.setIntervalSec(kIntervalSec);
+ rtcp.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+
+ amr.setAmrMode(kAmrMode);
+ amr.setOctetAligned(kOctetAligned);
+ amr.setMaxRedundancyMillis(kMaxRedundancyMillis);
+
+ evs.setEvsBandwidth(kEvsBandwidth);
+ evs.setEvsMode(kEvsMode);
+ evs.setChannelAwareMode(kChannelAwareMode);
+ evs.setUseHeaderFullOnly(kUseHeaderFullOnly);
+ evs.setCodecModeRequest(kcodecModeRequest);
+
+ config.setMediaDirection(kMediaDirection);
+ config.setRemoteAddress(kRemoteAddress);
+ config.setRemotePort(kRemotePort);
+ config.setRtcpConfig(rtcp);
+ config.setDscp(kDscp);
+ config.setRxPayloadTypeNumber(kRxPayload);
+ config.setTxPayloadTypeNumber(kTxPayload);
+ config.setSamplingRateKHz(kSamplingRate);
+ config.setPtimeMillis(kPTimeMillis);
+ config.setMaxPtimeMillis(kMaxPtimeMillis);
+ config.setDtxEnabled(kDtxEnabled);
+ config.setCodecType(kCodecType);
+ config.setTxDtmfPayloadTypeNumber(kDtmfTxPayloadTypeNumber);
+ config.setRxDtmfPayloadTypeNumber(kDtmfRxPayloadTypeNumber);
+ config.setDtmfsamplingRateKHz(kDtmfsamplingRateKHz);
+ config.setAmrParams(amr);
+ config.setEvsParams(evs);
+
+ session = new AudioSession();
+ const char testIp[] = "127.0.0.1";
+ unsigned int testPortRtp = 30000;
+ socketRtpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtp, AF_INET);
+ EXPECT_NE(socketRtpFd, -1);
+ unsigned int testPortRtcp = 30001;
+ socketRtcpFd = ImsMediaNetworkUtil::openSocket(testIp, testPortRtcp, AF_INET);
+ EXPECT_NE(socketRtcpFd, -1);
+ }
+
+ virtual void TearDown() override
+ {
+ if (session != nullptr)
+ {
+ delete session;
+ }
+
+ if (socketRtpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtpFd);
+ }
+
+ if (socketRtcpFd != -1)
+ {
+ ImsMediaNetworkUtil::closeSocket(socketRtcpFd);
+ }
+ }
+};
+
+TEST_F(AudioSessionTest, testLocalEndpoint)
+{
+ EXPECT_EQ(session->getState(), kSessionStateOpened);
+ EXPECT_EQ(session->getLocalRtpFd(), -1);
+ EXPECT_EQ(session->getLocalRtcpFd(), -1);
+
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->getLocalRtpFd(), socketRtpFd);
+ EXPECT_EQ(session->getLocalRtcpFd(), socketRtcpFd);
+}
+
+TEST_F(AudioSessionTest, testStartGraphFail)
+{
+ EXPECT_EQ(session->startGraph(nullptr), RESULT_INVALID_PARAM);
+ EXPECT_EQ(session->getState(), kSessionStateOpened);
+
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setRemoteAddress(android::String8(""));
+ EXPECT_EQ(session->startGraph(&config), RESULT_INVALID_PARAM);
+ EXPECT_EQ(session->getState(), kSessionStateOpened);
+}
+
+TEST_F(AudioSessionTest, testStartGraphAndUpdate)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ EXPECT_TRUE(session->IsGraphAlreadyExist(&config));
+
+ // normal update
+ config.setTxPayloadTypeNumber(120);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ // create one more graph
+ config.setRemotePort(20000);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 2);
+
+ config.setRemotePort(30000);
+ EXPECT_FALSE(session->IsGraphAlreadyExist(&config));
+}
+
+TEST_F(AudioSessionTest, testStartGraphSendOnly)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSending);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testStartGraphReceiveOnly)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateReceiving);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testStartGraphInactive)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testStartAndHoldResumeWithSameRemoteAddress)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testStartAndHoldResumeWithDifferentRemoteAddress)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ config.setRemotePort(20000);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->addGraph(&config, false), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ config.setRemotePort(30000);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE);
+ EXPECT_EQ(session->addGraph(&config, false), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testAddGraphWithoutStartGraph)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_INACTIVE);
+ EXPECT_EQ(session->addGraph(&config, false), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSuspended);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ config.setRemotePort(20000);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_SEND_ONLY);
+ EXPECT_EQ(session->addGraph(&config, false), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateSending);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+
+ config.setRemotePort(30000);
+ config.setMediaDirection(RtpConfig::MEDIA_DIRECTION_RECEIVE_ONLY);
+ EXPECT_EQ(session->addGraph(&config, true), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateReceiving);
+
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 2);
+}
+
+TEST_F(AudioSessionTest, testStartAddDeleteConfirmGraph)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ config.setRemotePort(20000);
+ EXPECT_EQ(session->addGraph(&config, true), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 2);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 2);
+
+ EXPECT_EQ(session->confirmGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+}
+
+TEST_F(AudioSessionTest, testStartAndAddWithRtcpOff)
+{
+ session->setLocalEndPoint(socketRtpFd, socketRtcpFd);
+ EXPECT_EQ(session->startGraph(&config), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+
+ config.setRemotePort(20000);
+ EXPECT_EQ(session->addGraph(&config, false), RESULT_SUCCESS);
+ EXPECT_EQ(session->getState(), kSessionStateActive);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpTx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtpRx), 1);
+ EXPECT_EQ(session->getGraphSize(kStreamRtcp), 1);
+} \ No newline at end of file